Bashのエレガントなシンプルさは、巨大なmanページで失われるようです。
上記の優れたソリューションに加えて、bashがステートメントをどのように解析および解釈するかについてのチートシートを提供したいと思いました。次に、このロードマップを使用して、質問者が提示した例を解析し、意図したとおりに動作しない理由をよりよく理解できるようにします。
注:シェルスクリプト行は直接使用されます。入力された入力行は最初に履歴展開されます。
各bash行は最初にトークン化されます。つまり、トークンと呼ばれるものに切り刻まれます。(トークン化は、中かっこ、チルダ、パラメータ、コマンド、算術、プロセス、単語分割、ファイル名展開など、他のすべての展開の前に行われます。)
ここでのトークンは、これらの特別なメタ文字のいずれかで区切られた(区切られた)入力行の一部を意味します。
space, - White space...
tab,
newline,
‘<’, - Redirection & piping...
‘|’,
‘>’
‘&’, - And/Both < | > | >> .or. &<file descriptor>
‘;’, - Command termination
‘(’, - Subshell, closed by - ‘)’
Bashは他の多くの特殊文字を使用しますが、これらの10個だけが初期トークンを生成します。
ただし、これらのメタ文字もトークン内で使用する必要がある場合があるため、それらの特別な意味を取り除く方法が必要です。これはエスケープと呼ばれます。エスケープは、1つ以上の文字のストリングを引用する(つまり'xx..'
、"xx.."
)か、個々の文字の前にバックスラッシュを付ける(つまり\x
)ことによって行われます。(引用符も引用する必要があり、二重引用符がすべてを引用するわけではないため、これよりも少し複雑になりますが、この単純化は今のところ行います。)
bashの引用を、他の言語のようにテキストの文字列を引用するという考えと混同しないでください。bashの引用符の間にあるのは文字列ではなく、トークンを区切らないようにメタ文字がエスケープされている入力行のセクションです。
'
、との間には重要な違いがありますが、それは"
また別の日です。
残りのエスケープされていないメタ文字は、トークンセパレータになります。
例えば、
$ echo "x"'y'\g
xyg
$ echo "<"'|'\>
<|>
$ echo x\; echo y
x; echo y
最初の例には、スペース区切り文字によって生成される2つのトークンがecho
ありxyz
ます。
2番目の例でも同様です。
第3の例ではセミコロンはエスケープので、スペース区切り文字によって生成される4つのトークンがあり、さecho
、x;
、echo
、およびy
。最初のトークンはコマンドとして実行され、次の3つのトークンを入力として受け取ります。2番目echo
は実行されないことに注意してください。
覚えておくべき重要なことは、そのbashの最初の文字をエスケープするためのルックス(ある'
、"
と\
)し、そのためには、エスケープメタ文字の区切り文字を探します。
エスケープされない場合、これらの10個の特殊文字はtoken
区切り文字として機能します。一部には追加の意味もありますが、何よりもまずトークン区切り文字です。
grepが期待するもの
grepの上記の例では、これらのトークンを必要としgrep
、string
、filename
。
質問の最初の試みは:
$ grep(then | there)xx
この場合(
、)
および|
エスケープメタ文字であるので、これらのトークンへの入力を分割するのに役立つ:grep
、(
、then
、|
、there
、)
、とx.x
。grepが見たいgrep
、then|there
とx.x
。
質問の2回目の試行は次のとおりです。
grep "(then | there)" xx
これはにトークン化しgrep
、(then|there)
、x.x
。エコー用にgrepを交換すると、これを確認できます。
echo "(then | there)" xx
(その後| there)xx