数ヶ月前、私は腕に フォーク爆弾 を入れ墨しました、そして私はそれがそれらなしでよりきれいに見えると思うので、私は空白をスキップしました。しかし、残念なことに、シェルで実行したときに 時には (常にではない)になってもfork bombが開始されず、構文エラーが発生するだけです。
bash: syntax error near unexpected token `{:'
昨日、友人の Bash Shellで実行しようとしたときに起こりました。その後、空白を追加したところ、突然:(){ :|:& };:
ではなく:(){:|:&};:
と動作しました。
空白は重要ですか。私の腕に構文エラーを入れ墨しましたか。
これは常に zsh で動作するようですが、Bashでは動作しません。
関連する質問 は空白については何も説明していません。これは本当に私の質問です。 Bashがそれを正しく解析するために空白が必要なのはなぜですか?
BASHのトークンを区切る文字のリストがあります。これらの文字はメタ文字と呼ばれ、|
、&
、;
、(
、 )
、<
、>
、スペースおよびタブ。一方、中括弧({
および}
)は、単語を構成する普通の文字です。
}
はメタキャラクターであるため、&
の前の2番目のスペースを省略します。したがって、タトゥーには少なくとも1つのスペース文字が必要です。
:(){ :|:&};:
タトゥーだけ
#!/bin/zsh
それ以上のShebangなら、あなたは大丈夫でしょう。
中括弧は特殊記号よりも奇妙なキーワードのようなもので、スペースが必要です。これは、たとえば括弧とは異なります。比較しなさい:
(ls)
これはうまくいき、そして
{ls}
これは{ls}
という名前のコマンドを探します。動作するには、それはする必要があります。
{ ls; }
セミコロンは閉じ括弧がls
へのパラメータとして扱われるのを止めます。
あなたがしなければならないのは、あなたがかなり狭いスペース文字でプロポーショナルフォントを使っていることを人々に言うことです。
タトゥーフォントでは簡単には見えませんが、実際にはブレースとコロンの間にバイトオーダーマーク(BOM)があります(タトゥーに気付かなかったときは酔っているかもしれませんが、実際にはそこにあります)。 。これには3つの明らかな可能性があります。
それから私は空白を追加し、それは突然働いた...
これはシェルがどのように解析するかのためです。関数定義の開始後、つまり{
の後にはスペースが必要です。
foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&}
有効です。一方、
foo() {echo hey&}
違います。
あなたは実際にはこのようなタトゥーが必要です。
ソースから :
/* We ignore an open brace surrounded by whitespace, and also
an open brace followed immediately by a close brace preceded
by whitespace. */
{
の後にスペースを省略すると、{echo
は単一のトークンとして解釈されます。
の等価形式
:(){ :|:& };:
だろう
:(){
:|:& };:
代替バージョンでは{
の後にスペースはありませんが、改行があるとシェルは{
をトークンとして認識します。