web-dev-qa-db-ja.com

メタ文字の周囲に空白が必要な場合があるのはなぜですか。

数ヶ月前、私は腕に フォーク爆弾 を入れ墨しました、そして私はそれがそれらなしでよりきれいに見えると思うので、私は空白をスキップしました。しかし、残念なことに、シェルで実行したときに 時には (常にではない)になってもfork bombが開始されず、構文エラーが発生するだけです。

bash: syntax error near unexpected token `{:'

昨日、友人の Bash Shellで実行しようとしたときに起こりました。その後、空白を追加したところ、突然:(){ :|:& };:ではなく:(){:|:&};:と動作しました。

空白は重要ですか。私の腕に構文エラーを入れ墨しましたか。

これは常に zsh で動作するようですが、Bashでは動作しません。

関連する質問 は空白については何も説明していません。これは本当に私の質問です。 Bashがそれを正しく解析するために空白が必要なのはなぜですか?

537
spydon

BASHのトークンを区切る文字のリストがあります。これらの文字はメタ文字と呼ばれ、|&;()<>スペースおよびタブ。一方、中括弧({および})は、単語を構成する普通の文字です。

}はメタキャラクターであるため、&の前の2番目のスペースを省略します。したがって、タトゥーには少なくとも1つのスペース文字が必要です。

:(){ :|:&};:
266
Dmitri Chubarov

タトゥーだけ

#!/bin/zsh

それ以上のShebangなら、あなたは大丈夫でしょう。

78
SzG

中括弧は特殊記号よりも奇妙なキーワードのようなもので、スペースが必要です。これは、たとえば括弧とは異なります。比較しなさい:

(ls)

これはうまくいき、そして

{ls}

これは{ls}という名前のコマンドを探します。動作するには、それはする必要があります。

{ ls; }

セミコロンは閉じ括弧がlsへのパラメータとして扱われるのを止めます。

あなたがしなければならないのは、あなたがかなり狭いスペース文字でプロポーショナルフォントを使っていることを人々に言うことです。

50
Peter Westlake

タトゥーフォントでは簡単には見えませんが、実際にはブレースとコロンの間にバイトオーダーマーク(BOM)があります(タトゥーに気付かなかったときは酔っているかもしれませんが、実際にはそこにあります)。 。これには3つの明らかな可能性があります。

  1. コードを転記したときにBOMを入力できませんでした。結果はGIGOの明らかな応用です。シェルはあなたの失敗した書き起こしに存在しないBOMを単に認識しません。
  2. あなたの殻は古すぎる。これはUnicode文字を認識しないので、ファイルの先頭以外のBOMは幅がゼロで改行のないスペースとして扱われることになっていても、BOM(そしておそらく他のすべてのUnicode文字)は完全に無視されます。 。
  3. あなたの殻は新しすぎる。 ZWNBSとしてのBOMの使用は推奨されておらず、著者はこの使用法がもはや許されない将来のバージョンのUnicodeを実装しました。
40
Jerry Coffin

それから私は空白を追加し、それは突然働いた...

これはシェルがどのように解析するかのためです。関数定義の開始後、つまり{の後にはスペースが必要です。

foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&}

有効です。一方、

foo() {echo hey&}

違います。


あなたは実際にはこのようなタトゥーが必要です。

enter image description here


ソースから

  /* We ignore an open brace surrounded by whitespace, and also
     an open brace followed immediately by a close brace preceded
     by whitespace.  */

{の後にスペースを省略すると、{echoは単一のトークンとして解釈されます。


の等価形式

:(){ :|:& };:

だろう

:(){
:|:& };:

代替バージョンでは{の後にスペースはありませんが、改行があるとシェルは{をトークンとして認識します。

40
devnull