なぜメタキャラクターの周りに空白が必要なのですか?


543

数か月前に腕にフォーク爆弾を入れて、空白を省いたので見た目が良かったのでスキップしました。しかし、残念なことに、シェルで実行すると(常にではありませんが)、フォーク爆弾が開始されないことがありますが、構文エラーが発生します。

bash: syntax error near unexpected token `{:'

昨日、私は友人の中でそれを実行しようとしたときにそれは起こったのBashシェル、そして私は空白を追加し、それが急に働いた、:(){ :|:& };:代わりに:(){:|:&};:

空白は重要ですか。腕の構文エラーにタトゥーを入れましたか?!

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

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


6
私は同じ質問をここに投稿しました(タトゥー部分を除く)。
Benoit

3
また、コロン(:)を関数名として使用することはできません(参照:pubs.opengroup.org/onlinepubs/9699919799/utilities/…)... FreeBSDの/ bin / shでも、このエラーが発生します...
Martin Tournoij、2014年

5
@Carpetsmoker:それがどのように関連しているかはわかりません。この質問はバッシュについてです。
デニス

回答:


267

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

はメタ文字な}ので、前の2番目のスペースを省略して&もかまいません。したがって、タトゥーには少なくとも1つのスペース文字が必要です。

:(){ :|:&};:

35
簡単な解決策:タオの最初の部分を左に移動し、2つの部分の間に皮膚を移植します。

23
私は言葉が好きだったon the other hand...意図されたしゃれ?;):D(申し訳ありませんが、トピックコメントを
削除しました

4
しかし、これはzshでは異なりますか?zshはどのように異なりますか?
tfogo 2014年

2
この説明では、{}シェルキーワードであることを除いて、良い説明です。それらがそのように認識されない場合のみ-周囲のスペース/メタ文字がないために-それらは、それらが含まれる単語の文字どおりの部分として扱われます。(そして、ブレースの展開があり、これは別のコンテキストで発生します。)
mklement0

2
@DmitriChubarov中かっこは、コマンド名(関数を含む:{foo} () { echo hello; }。 "名前"で使用できます。 " bash英数字"とアンダースコアのみで構成され、英字またはアンダースコアで始まる単語 "は、変数名にのみ適用されます。
chepner

82

ただ入れ墨、

#!/bin/zsh

その上にシバンとあなたは大丈夫です。


6
我々している好き嫌い場合は、プロンプト...によって証明されるように、シェバングは、すべての作業は、シェルとして、うまくいけばzshの、インタラクティブモードになっていないだろう
SZG

50

中かっこは、特殊記号よりも奇妙なキーワードに似ており、スペースが必要です。これは、たとえば括弧とは異なります。比較:

(ls)

うまくいく、そして:

{ls}

というコマンドを探します{ls}。機能するには、次の条件を満たしている必要があります。

{ ls; }

セミコロンは、右中括弧がへのパラメーターとして取られるのを停止しますls

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


12
@DmitriChubarov-非常に卑劣なトリックであり、ブレースの完全に異なる意味を使用します。値のコンマ区切りリスト(この場合は単なる)を展開しlsます。
Peter Westlake、2014年

7
しかし…男の子…あなたは残りの人生で入れ墨をするつもりです!あなたはいつも自分をオタクだとマークしました!そしてあなたはそれをステッチする前にそれを正しく得ることさえできなかったのですか?それは私が推測するオタクであることを超えた2つのステップです;-)いいえ、仲間、私はただ不思議に思っています。
Alfe、2014年

14
@Alfeタトゥーを入れる前に試しましたが、zshで試しましたが、bashと同じ解析であると思いました。ばかげているが、それはzshだと人々に話すだけだ。:)
スパイドン2014年

20
@spydonそれとも、あなたの入れ墨からのコマンドをコピーしている人が誤ってそれを実行し、自分のマシンがクラッシュすることはありませんので、あなたが目的のスペースを残していることを伝え;)
突く

4
ねえ、それがzshで有効な場合は、そのすぐ上(またはその前)に#!/ bin / zshを追加しないでください。とにかく、最初にシェルを指定することをお勧めします。
Adam Miller

41

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

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

40

そして、私は空白を加えました、そして、それは突然働きました...

シェルの解析方法が原因です。関数定義の開始後、つまりの後にスペースが必要{です。

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単一のトークンとして解釈されます。


同等の形式

:(){ :|:& };:

だろう

:(){
:|:& };:

{代替バージョンでは後にスペースがないことに注意してください。ただし、改行により、シェル{はトークンとして認識されます。


「{の後にスペースを省略すると、{echoは単一のトークンとして解釈されます。」-では、パーサー{echoは、必要な開始中括弧に達する前に呼び出されたコマンドに遭遇したと考えていますか?
ジョナ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.