무슨 사이의 차이점 <<
, <<<
그리고 < <
bash는?
무슨 사이의 차이점 <<
, <<<
그리고 < <
bash는?
답변:
여기 문서
<<
라고도 here-document
구조. 종료 텍스트가 무엇인지 프로그램에 알리고 구분 기호가 표시 될 때마다 프로그램은 입력 한 모든 내용을 입력으로 읽고 작업을 수행합니다.
여기 내가 의미하는 바가있다 :
$ wc << EOF
> one two three
> four five
> EOF
2 5 24
이 예제에서 우리는 wc
프로그램에게 EOF
문자열 을 기다렸다가 5 단어를 입력 한 다음 입력 EOF
하여 입력을 완료했다는 신호를 보냅니다. 실제로 wc
자체적 으로 실행 하고 단어를 입력 한 다음CtrlD
bash에서는 임시 파일을 통해 일반적으로 형식 /tmp/sh-thd.<random string>
으로 구현되며 대시에서는 익명 파이프로 구현됩니다. 이것은 strace
명령을 사용 하여 추적 시스템 호출을 통해 확인할 수 있습니다 . 교체 bash
와 sh
방법을 보려면 /bin/sh
이 리디렉션을 수행합니다.
$ strace -e open,dup2,pipe,write -f bash -c 'cat <<EOF
> test
> EOF'
여기 문자열
<<<
로 알려져 있습니다 here-string
. 텍스트를 입력하는 대신 미리 만든 텍스트 문자열을 프로그램에 제공합니다. 예를 들어, 특정 사례에 대한 출력을 얻기 위해 bc
할 수있는 프로그램을 사용 bc <<< 5*4
하면 대화식으로 bc를 실행할 필요가 없습니다.
bash의 here-string은 임시 파일을 통해 일반적으로 형식화 /tmp/sh-thd.<random string>
되어 나중에 연결이 해제되므로 일부 메모리 공간을 일시적으로 차지하지만 /tmp
디렉토리 항목 목록에는 표시되지 않으며 익명 파일로 효과적으로 존재합니다. 쉘 자체에 의해 파일 디스크립터를 통해 참조되고, 파일 디스크립터는 명령에 의해 상속되고 나중에 dup2()
함수 를 통해 파일 디스크립터 0 (stdin)에 복제 됩니다. 이것은 통해 볼 수 있습니다
$ ls -l /proc/self/fd/ <<< "TEST"
total 0
lr-x------ 1 user1 user1 64 Aug 20 13:43 0 -> /tmp/sh-thd.761Lj9 (deleted)
lrwx------ 1 user1 user1 64 Aug 20 13:43 1 -> /dev/pts/4
lrwx------ 1 user1 user1 64 Aug 20 13:43 2 -> /dev/pts/4
lr-x------ 1 user1 user1 64 Aug 20 13:43 3 -> /proc/10068/fd
그리고 (출력 가독성 단축 콜 추적을 통해, 임시 파일을 FD (3)에 쓸 데이터 그때는 재 개방으로 개방되는 방식을 통지 O_RDONLY
한 후, FD 4로 플래그 나중에 해제 dup2()
상속 FD 0에, cat
나중에 ) :
$ strace -f -e open,read,write,dup2,unlink,execve bash -c 'cat <<< "TEST"'
execve("/bin/bash", ["bash", "-c", "cat <<< \"TEST\""], [/* 47 vars */]) = 0
...
strace: Process 10229 attached
[pid 10229] open("/tmp/sh-thd.uhpSrD", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
[pid 10229] write(3, "TEST", 4) = 4
[pid 10229] write(3, "\n", 1) = 1
[pid 10229] open("/tmp/sh-thd.uhpSrD", O_RDONLY) = 4
[pid 10229] unlink("/tmp/sh-thd.uhpSrD") = 0
[pid 10229] dup2(4, 0) = 0
[pid 10229] execve("/bin/cat", ["cat"], [/* 47 vars */]) = 0
...
[pid 10229] read(0, "TEST\n", 131072) = 5
[pid 10229] write(1, "TEST\n", 5TEST
) = 5
[pid 10229] read(0, "", 131072) = 0
[pid 10229] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=10229, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
의견 : 잠재적으로 here 문자열은 임시 텍스트 파일을 사용하기 때문에 POSIX 정의에 의한 텍스트 파일 에는 줄 바꿈 문자로 끝나는 줄이 있어야하기 때문에 here-string이 항상 줄 바꿈 개행을 삽입하는 가능한 이유 입니다.
프로세스 대체
tldp.org가 설명 하듯이
프로세스 대체는 프로세스 (또는 프로세스)의 출력을 다른 프로세스의 stdin에 공급합니다.
실제로 이것은 하나의 명령의 stdout 을 다른 명령으로 파이프하는 것과 유사합니다 echo foobar barfoo | wc
. 그러나 bash 맨 페이지 에서 으로 표시되어 있음을 알 수 <(list)
있습니다. 따라서 기본적으로 여러 (!) 명령의 출력을 리디렉션 할 수 있습니다.
참고 : 기술적 < <
으로 한 가지를 언급하는 것이 아니라 <
출력의 단일 및 프로세스 리디렉션을 사용 하여 두 가지 리디렉션 을 말합니다 <( . . .)
.
대체 처리 만하면 어떻게됩니까?
$ echo <(echo bar)
/dev/fd/63
보시다시피, 쉘은 /dev/fd/63
출력이 진행되는 임시 파일 디스크립터를 생성합니다 ( Gills의 답변 에 따르면 익명 파이프 임). 즉, <
해당 파일 디스크립터를 입력으로 명령에 리디렉션합니다.
따라서 매우 간단한 예는 두 개의 echo 명령 출력을 wc로 프로세스 대체하는 것입니다.
$ wc < <(echo bar;echo foo)
2 2 8
따라서 여기서는 쉘이 괄호 안에 발생하는 모든 출력에 대한 파일 디스크립터를 작성하고이를 입력으로 경로 재 지정합니다 wc
. 예상대로, wc는 두 개의 echo 명령에서 해당 스트림을 수신합니다. 적절하게 우리는 2 단어, 2 줄 및 6 문자와 2 줄 바꿈이 있습니다.
사이드 참고 : 프로세스 대체가로 불릴 수있다 bashism (명령 또는 같은 고급 쉘에서 사용할 수있는 구조 bash
지만, POSIX에 의해 지정되지 않음) 있지만 구현되었습니다 ksh
이전 배쉬의 존재 KSH man 페이지 와 이 답변이 좋습니다. 같은 쉘 tcsh
및 mksh
그러나 공정 대체가 없습니다. 그렇다면 프로세스 대체없이 여러 명령의 출력을 다른 명령으로 리디렉션하는 방법은 무엇입니까? 그룹화 및 파이핑!
$ (echo foo;echo bar) | wc
2 2 8
실제로 이것은 위의 예와 동일하지만 전체 서브 쉘의 stdout을 만들고 wc
파이프와 연결된 stdin을 만들기 때문에 이는 프로세스 대체 와 차이가 있습니다 . 반면에 프로세스 대체는 명령이 임시 파일 디스크립터를 읽도록합니다.
파이핑으로 그룹화 할 수 있다면 왜 프로세스 대체가 필요한가? 때로는 파이프를 사용할 수 없기 때문입니다. 아래의 예를 고려하십시오-두 개의 명령의 출력과 두 diff
개의 파일이 필요하며이 경우 두 개의 파일 설명자를 제공합니다.
diff <(ls /bin) <(ls /usr/bin)
< <
프로세스 대체 에서 stdin을 가져올 때 사용됩니다 . 이러한 명령은 다음과 같습니다 cmd1 < <(cmd2)
.. 예 :wc < <(date)
< <
그 자체만으로는 문제가되지 않습니다. 프로세스 대체의 경우에는 <
그 다음에 나오는 다른 항목이 있습니다.<
<<<
Plan 9 rc shell의 유닉스 포트에 의해 처음 구현 된 후 나중에 zsh, bash 및 ksh93에 의해 채택되었습니다. 나는 그것을 bashism이라고 부르지 않을 것이다.
echo 'foo' | read; echo ${REPLY}
것 없는 반환 foo
하기 때문에, read
- 배관 하위 쉘을 시작하는 서브 쉘에서 시작됩니다. 그러나 하위 쉘이 없기 때문에 read < <(echo 'foo'); echo ${REPLY}
올바르게 리턴합니다 foo
.
< <
구문 오류입니다.
$ cat < <
bash: syntax error near unexpected token `<'
< <()
인 프로세스 교체 ( <()
(재로 결합 된) <
) :
고안된 예 :
$ wc -l < <(grep ntfs /etc/fstab)
4
$ wc -l <(grep ntfs /etc/fstab)
4 /dev/fd/63
프로세스 대체에서는 파일 디스크립터의 경로가 파일 이름처럼 사용됩니다. 파일 이름을 직접 사용하고 싶지 않거나 사용할 수없는 경우 프로세스 대체와 리디렉션을 결합합니다.
명확히하기 위해 < <
연산자 가 없습니다 .
<()
는 파일 이름과 같은 것을 제공하므로 더 일반적으로 유용합니다- < <()
필요하지 않은 stdin을 대체하는 것입니다. 에서 wc
, 후자는 더 유용하게 발생합니다. 다른 곳에서는 그다지 유용하지 않을 수도 있습니다
< <
구문 오류가 발생합니다. 올바른 사용법은 다음과 같습니다.
예제의 도움으로 설명 :
예 < <()
:
while read line;do
echo $line
done< <(ls)
위의 예에서 while 루프에 대한 입력은 ls
명령 에서 나옵니다. 명령은 한 줄씩 읽고 루프에서 사용할 수 있습니다 echo
.
<()
프로세스 대체에 사용됩니다. 자세한 정보와 예 <()
는이 링크에서 찾을 수 있습니다.