私が知っている最も簡単なのは<
ファイル入力を許可するコマンドですが
grep search-word <filename
grep search-word < filename
、この場合スペースは重要ではありません。
ただし、どちらの場合も1つの構文のみが機能し、他の場所にスペースを入れることは機能しません。
(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
<
、<<
3つの<(
異なる演算子です。演算子内にスペースを含めることはできませんが、場合によってはシェルが意味を正しく識別するのに役立つように演算子間にスペースが必要です。
語彙アナライザの一般的な動作は、有効な演算子を生成する最も長い文字セットを食べて、その演算子を表すトークンをパーサに返すことです。その後、パーサーは言語の実際の文法を処理します。
たとえば、
cat < filename
3つのトークン「wordcat
」、「入力リダイレクト演算子」、および「wordfilename
」が生成されます。cat << EOF
「wordcat
」、「heredoc演算子」、「wordEOF
」を生成します。cat < < EOF
cat
4つのトークン「word」、「入力リダイレクト演算子」、「入力リダイレクト演算子」、「word」を生成しますEOF
が、これは構文上意味がなく、エラーを生成します。cat<filename
<
文字は引用しない限り、単語の一部にすることはできないため、最初の文字と同じように動作するため、ここではマークアップが中断されます。
同様に<(
、プロセス置換の開始ですが、< (
2つの演算子のみがあり、スペースで区切ら<
れ(
ているためです。そして、最長の接頭辞の一致のため、<<(
here-doc演算子<<
の後に(
andが続きます。いいえリダイレクト演算子<
の後にプロセスの交換が開始されます。おそらくこれはより有用な説明です。
最長のプレフィックスを採用する行為は、他の言語でも一般的です。たとえば、Cでは、i+++a
(or)と同様に、最初の後ろにスペースが必要です。どちらも有効な表現ですが、意味が異なるだけです。 C ++では、長い間入れ子になったテンプレートをで書く必要がありました。これは、空白がない場合は、テンプレート構文で必要な2つの演算子ではなく、無関係な右移動演算子として扱われたためです。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
これはシェル演算子を解析する方法と同じではありません。