這些特殊的左 < 是什麼以及為什麼空格很重要?
我知道簡單
<
的是接受來自文件的輸入的命令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歲那樣解釋嗎?謝謝。
這三個東西
<
,<<
和<(
是不同的運算符。運算符中不能有空格,但在某些情況下,它們之間需要空格以幫助 shell 正確辨識您的意思。詞法分析器的通常行為是吃掉產生有效運算符的最長字元集,然後將表示該運算符的標記返回給解析器,然後解析器處理語言的實際語法。
例如:
cat < filename
產生三個標記“單詞cat
”,“輸入重定向運算符”,“單詞filename
”。cat << EOF
產生“單詞cat
”、“heredoc 運算符”、“單詞EOF
”和cat < < EOF
會產生四個標記“單詞cat
”、“輸入重定向運算符”、“輸入重定向運算符”、“單詞EOF
”,但這在語法上沒有意義並給出錯誤。cat<filename
行為與第一個相同,因為<
除非引用,否則該字元不能成為單詞的一部分,因此標記在那里中斷。同樣,
<(
是程序替換的開始,但< (
只是兩個運算符<
,並且(
因為空格將它們打斷。而且,由於最長前綴匹配,<<(
here-doc 運算符<<
後面是 the(
而不是重定向運算符<
後面是程序替換的開始,即使這可能是更有用的解釋。採用最長前綴的行為在其他語言中也很常見。例如,在 C 中,與(或)
i+++a
相同,對於,您需要在第一個 之後的空格。兩者都是有效的表達方式,它們只是意味著不同的東西。在 C++ 中,很長時間以來,您必須將嵌套模板編寫為,因為沒有空格,將被視為不相關的右移運算符,而不是模板語法所需的 two 。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
,但這與 shell 運算符的解析方式不同。