내가 아는 가장 간단한 것은 <
파일 입력을 허용하는 명령인데
grep search-word <filename
grep search-word < filename
, 이 경우 공백은 중요하지 않습니다.
그러나 두 경우 모두 하나의 구문만 작동하며 다른 곳에 공백을 넣는 것은 작동하지 않습니다.
(gdb) r < <(python -c "print('\x44\x43\x42\x41')")
작동
(gdb) r << (python -c "print('\x44\x43\x42\x41')")
하지 않습니다.
(gdb) r<<(python -c "print('\x44\x43\x42\x41')")
작동하지 않습니다.
아니면 여기
sshpass -f <(printf '%s\n' $PASSWORD)
작동
sshpass -f < (printf '%s\n' $PASSWORD)
하지 않습니다.
sshpass -f<(printf '%s\n' $PASSWORD)
작동하지 않습니다.
왜 그런 겁니까? 5살짜리 나에게 이것을 설명해 줄 수 있는 사람이 있나요? 감사해요.
답변1
<
, <<
세 가지가 <(
서로 다른 연산자입니다. 연산자 내에 공백이 있을 수 없지만 어떤 경우에는 쉘이 의미를 올바르게 식별하는 데 도움이 되도록 연산자 사이에 공백이 필요합니다.
어휘 분석기의 일반적인 동작은 유효한 연산자를 생성하는 가장 긴 문자 집합을 먹고 해당 연산자를 나타내는 토큰을 파서에 반환하는 것입니다. 그러면 파서는 언어의 실제 문법을 처리합니다.
예를 들어:
cat < filename
세 개의 토큰 "wordcat
", "입력 리디렉션 연산자" 및 "wordfilename
"가 생성됩니다.cat << EOF
"wordcat
", "heredoc 연산자", "wordEOF
"를 생성합니다.cat < < EOF
cat
4개의 토큰 "word ", "입력 리디렉션 연산자", "입력 리디렉션 연산자", "word " 를 생성EOF
하지만 이는 구문상 의미가 없으며 오류를 생성합니다.cat<filename
<
문자는 인용되지 않는 한 단어의 일부가 될 수 없으므로 첫 번째 문자와 동일하게 동작하므로 여기서 마크업이 중단됩니다.
마찬가지로 <(
프로세스 대체의 시작이지만 < (
두 개의 연산자만 있고 <
공백 (
으로 구분되기 때문입니다. 그리고 가장 긴 접두사 일치로 인해 <<(
here-doc 연산자 <<
뒤에는 (
and가 옵니다.아니요리디렉션 연산자 <
뒤에는 프로세스 교체가 시작됩니다. 아마도 이것이 더 유용한 설명일 것입니다.
가장 긴 접두사를 채택하는 행위는 다른 언어에서도 흔히 볼 수 있습니다. 예를 들어 C에서는 i+++a
(or)와 마찬가지로 첫 번째 뒤에 공백이 필요합니다. 둘 다 유효한 표현이지만 의미가 다를 뿐입니다. C++에서는 오랫동안 중첩된 템플릿을 로 작성해야 했습니다. 공백이 없으면 템플릿 구문에서 요구하는 두 가지 연산자 대신 관련 없는 오른쪽 이동 연산자로 처리되었기 때문입니다.i ++ + a
i++ + a
i + ++a
+
vector<vector<int> >
>>
>
즉, 마지막 명령은sshpass -f<(printf '%s\n' $PASSWORD)
~해야 한다와 동일하게 작동 cat<filename
하며 실제로 저에게 효과적이었습니다.
$ sshpass -f<(echo password) ssh foo@localhost 'echo hi'
hi
set -x
실제 명령 실행은 다음과 같습니다 .
sshpass -f/dev/fd/63 ssh foo@localhost 'echo hi'
즉, 프로세스를 보기 전에 파일 이름으로 바꾸십시오 sshpass
. 일부 프로그램의 경우 -f foo
및 사이에 차이가 있을 수 있지만 -ffoo
이는 쉘 연산자가 구문 분석되는 방식과 동일하지 않습니다.