
長い話を短く:POSIX中括弧グループでは予約語の後にスペースが必要です{
が、サブシェルでは予約語の後にスペースが必要ないのはなぜですか(
?
POSIX シェル構文は、中かっこグループとサブシェルを次のように定義します。
brace_group : Lbrace compound_list Rbrace
subshell : '(' compound_list ')'
さて、これを文字通り受け入れればスペースが大切です。これは、次のように、括弧だけでなく、開かれたかっこと閉じられた中かっこを表示するスペースがあることを意味します。
{ echo hello world; }
( echo hello world )
これも次のように一致します。複合コマンドの定義:
これらの複合コマンドのそれぞれには、先頭に予約語または制御演算子があり、最後に対応する終端予約語または演算子があります。
しかし、理解できないのは理由であり、うまくいきますが(末尾のスペースは(list)
必要ありません)、中括弧の拡張には先行スペースが必要です。つまり、動作しません。( list )
(
{echo hello;}
もちろん、予約語をシェル語として扱うのは合理的であり、概念と一致するためには後に空白が必要です。フィールド分割しかし、定義自体はスペースについて言及しません。また、複合コマンドのPOSIX定義が予約語と{
両方を処理する場合、これらの予約語の後の空白文字に関して異なる方法で処理されるのはなぜですか?(
今、クッシュ(1)マニュアルには次のように記載されています。
単語は、引用符のない空白文字(スペース、タブ、および改行)またはメタ文字(<、>、|、;、&、(および))で区切られた一連の文字です。
つまり、kshが(
最初の単語がコマンドまたは変数割り当てである単語区切り文字として認識するのは妥当です。しかし、POSIXではメタ文字に言及していないようです(
。 POSIXの構文の観点から私が見つけた唯一の説明は{
「トークン」として扱われ、asは(
それらの1つとしてリストされていないということです。
/* These are reserved words, not operator tokens, and are
recognized when reserved words are recognized. */
%token Lbrace Rbrace Bang
/* '{' '}' '!' */
それでは、これらの違いが発生する正確な理由は何ですか?
承認された回答コメント:
許可されたチェックマークを次に移動します。イサクの答えqを提供するため参考文献フォーム標準それ自体で私の問題を自分で解決しました。
たとえば、「(」と「)」は制御演算子であるため、(
<space>
リスト)には必要ありません。ただし、「{」と「}」は{list;}の予約語であるため、この場合は先行合計が必要です<space>
。<semicolon>
Kosalonandaの回答を受け入れてください。 Kusaranandaの答えは、主に非公式で直感的な観点から私の要件を満たしていましたが、{
isは予約語であり、(
is演算子であることを指摘しました。 Michael Homerはコメントで同じ状況を指摘しました。複合コマンド定義の状態(強調追加):これらの複合コマンドのそれぞれに予約語があります。または制御演算子最初に
{
Shell Grammarに似ているか、リストされているfor
予約語として定義されていますwhile
(質問の最後のコードブロックを参照)。セクション2.9では、次のように説明します(ハイライトを追加)。
特に、これらの表現はマーカー間の間隔を含む。sを必要としないいくつかの
<blank>
場所(トークンの1つがオペレータである場合)。(
演算子は標準によって明示的に定義されていませんが、(
単に演算子と呼ばれます。セクション2.9.2説明するパイプが予約語で始まる場合!そしてcommand1はサブシェルコマンドなので、アプリケーションはcommand1の先頭にある(演算子が!で1つ以上の文字で区切られていることを確認する必要があります。(演算子の直後にある予約語!の動作は指定されていません)。
スタックオーバーフローに関する質問Digital Traumaは予約語のセクション2.4を指摘しています。
この認識は、文字が引用されず、単語が次のように使用される場合にのみ発生します。
- コマンドの最初の単語
Kusalanandaの答えで述べたように、「POSIX構文に示されている空白は、シェル入力データに含まれる必要がある空白ではなく、構文自体を表示する方法です。マイケル・ホーマーコメント:「これらのスペースがそれ自体にとって重要である場合は、リストする必要があります。生産」
場合閉鎖。
答え1
中括弧と括弧の違いは、中括弧(および)は、etc!
などの予約語で、括弧は制御演算子です。単語はスペースで区切る必要があります。for
if
then
持てないという意味だ
foriin*; do
あなたは持つことができません
{somecommand;} >file
または
if !somecommand; then
POSIX構文に表示される空白は、シェル入力データに含まれるべき空白ではなく、構文自体を表示する方法にすぎません。実際、中かっこは予約されています。性格つまり、サブシェル括弧はスペースで囲む必要がありますが、そうではありません。
答え2
これは、シェルが行をトークンに分割する方法の制限です。
殻にこう書いています。ワイヤー入力ファイルからセクション2「シェルについて」によるとそれらに変換言葉またはオペレーター:
- シェルは入力をトークン(単語と演算子)に分割します。
{は予約語です
予約語はシェルに特別な意味を持つ単語です。次の単語は予約語と見なされるべきです。
! { } case do done elif else esac fi for if in then until while
テキストとして認識されるテキスト、でなければならない分離。
予約語は区切りの場合にのみ認識されます。
最大スペースで構成されている(ポイント7)そしてオペレータによって。
- 現在の文字が引用符なしの<空白>の場合、前の文字を含むトークンは区切り、現在の文字は削除されます。
(は演算子です
演算子自体が区切り記号です。
どこ「運営者」は:
3.260 演算子
シェルコマンド言語では、次のいずれかを実行します。コントロールオペレーターまたはリダイレクトオペレーター。
リダイレクト演算子
シェルコマンド言語でリダイレクト機能を実行するトークンです。次の記号のいずれかです。
< > >| << >> <& >& <<- <>
3.113 制御演算子
シェルコマンド言語で制御機能を実行するタグ。次の記号のいずれかです。
& && ( ) ; ;; newline | ||
結論として
したがって、「(」および「)」は制御演算子であり、「{」および「}」は予約語です。
そしてまったく同じ説明問題は仕様内です。:
たとえば、「(」と「)」は制御演算子であるため、(リスト)には<space>は必要ありません。ただし、「{」と「}」は{list;}の予約語なので、この場合は前に<space>と<semicolon>が必要です。
これはその理由を正確に説明します{
。
これは働きます:
{ echo yes;}
このように:
{(echo yes);}
これ:
{(echo yes)}
またはこれも:
{>/dev/tty echo yes;}