`(`,`)`と`test`のPOSIX記述を理解する方法は?

`(`,`)`と`test`のPOSIX記述を理解する方法は?

~からPOSIX 2013:

-a および -o デフォルトのバイナリと「(」および「)」演算子を指定する XSI 拡張は、廃止とマークされています。 (これを使用する多くの式は、評価される特定の式に従って構文によってあいまいに定義されます。)これらの式を使用するスクリプトは、以下の形式に変換する必要があります。多くの実装はこれらの役に立たない形式をサポートし続けますが、スクリプトはユーザー提供の入力を処理するときに非常に注意する必要があります。これは、これらの基本と演算子と混同される可能性があるためです。アプリケーション開発者がスクリプトへの入力を生成するすべての状況を知らない限り、次のように呼び出します。

test "$1" -a "$2"

次のように書く必要があります。

test "$1" && test "$2"

  1. "'(' および ')' 演算子は廃止予定としてマークされました。"

    ()コマンドをグループ化してサブシェルを生成する演算子は何ですか?

    使用されなくなった場合の代替品とは何ですか?

  2. test "$1" -a "$2"に交換する必要がありますかtest "$1" && test "$2"、またはに交換する必要がありますか(( test "$1" && test "$2" ))

    ((...))元のコマンドのように0または1を返す必要はありませんか?test

答え1

()コマンドをグループ化してサブシェルを生成する演算子は何ですか?

いいえ、ドキュメントでは、次を使用して式をグループ化する演算子を参照しますtest

test 0 -eq 0 -a \( 0 -eq 1 -o 1 -eq 1 \)

使用されなくなった場合の代替品とは何ですか?

代替コマンドはおよび(){}、これはシェルレベルで同様にコマンドをグループ化します。

test 0 -eq 0 && (test -0 -eq 1 || test 1 -eq 1)
test 0 -eq 0 && { test -0 -eq 1 || test 1 -eq 1; }

パターンを見るのは簡単です。testfor式で使用されているすべての演算子は、シェル内の対応するforコマンドに置き換えられます。

test "$1" -a "$2"に交換する必要がありますかtest "$1" && test "$2"、またはに交換する必要がありますか(( test "$1" && test "$2" ))

算術式を評価することが目的であるため、命令の終了状態に関係なく算術拡張のためにtest "$1" && test "$2"。に変更する必要があります。(())たとえば、次は有効です。

(( $(test 1 -eq 1 && echo $?) && $(test 0 -eq 0 && echo $?) ))

0(コマンドの置き換えに注意してください。内部コマンドの終了ステータスに置き換えられ、評価された0式は実際にはです(( 0 && 0 ))。)

ただし、これにより構文エラーが発生します。

(( test 1 -eq 1 && test 0 -eq 0 ))
$ (( test 1 -eq 1 && test 0 -eq 0 ))
bash: ((: test 1 -eq 1 && test 0 -eq 0 : syntax error in expression (error token is "1 -eq 1 && test 0 -eq 0 ")

答え2

より簡単な言語で非常に重要な事実を強調するには:

画面に入力した文字は、呼び出したコマンドによって「表示」(受信)されることも、そうでない場合もあります。あなたはおそらく何かを引用するたびにこれが起こるという事実に精通しているでしょう。

これシェル入力したすべての文字を確認してください。シェルには、これらの文字を処理する方法に関する独自の規則があります。たとえば、このechoコマンドは、次の各インスタンスでまったく同じ内容を「確認」します。

$ echo hello
hello
$ echo "hello"
hello
$ echo 'hello'
hello
$ echo \h\e\l\l\o
hello
$ echo 'h'"e"\l$'lo'
hello
$ somevar=hello;echo $somevar
hello
$ somevar='h'"el"\l\o;echo $somevar
hello
$ 

コマンドが上記の引用符とバックスラッシュを「認識」しないように、echoシェルは括弧を具体的に処理します。だから、引用しない場合、彼らはシェル以外のものには見えません。

find良い例は、括弧を次のように許可するコマンドです。議論。ブラケットの場合到着コマンドはfindシェルで特に解釈されないため、シェルから特別な意味を削除するには、引用またはエスケープする必要があります。引用符とエスケープいいえリーチfindコマンド括弧のみ使用可能:

(から別の問題このサイトから:)

# What you type:
find ~ \( -type f '-ex'ec ch\mod 600 {} + ')' -o \
       "(" -type d -exec c"hmo"d 700 {} ';' \)
# What the find command sees:
/home/tim ( -type f -exec chmod 600 {} + ) -o ( -type d -exec chmod 700 {} ; )
# If you typed this...
find ~ \( -type f -exec chmod 600 {} + ) -o \
       \( -type d -exec chmod 700 {} + \)
# ...find doesn't see anything, because bash runs into an error condition
# before it can even parse the line.  That close paren is special to bash.

これに関連する俗語もあります。コマンドで特殊文字(通常は一重引用符または二重引用符、バックスラッシュ、スペース文字も含めることができます)を「表示」しようとしていますが、引用やエスケープのバグによってそのコマンドがその文字を表示できない場合は、 。シェルは参照を「食べる」。

引用符を食べる(およびそれを囲むのが難しい)興味深い例には、リモートサーバーにログインしてbashセッションを開始し、コマンドを実行してファイルに保存されているファイルを修正してsed正しく参照できるsshコマンドを作成することが含まれます。メッセージのHTTPに含まれます。


もしそうなら、短い答えは次のようになります。

  1. "'(' および ')' 演算子は廃止予定としてマークされました。"

コマンドをグループ化してサブシェルを生成する(および)演算子ですか?

使用されなくなった場合の代替品とは何ですか?

括弧はまだシェルで特別な意味を持ち、役に立たない。使用されなくなったのは、括弧をコマンドに渡すことですtest(シェルが括弧を食べないようにするために引用)。


*これは明らかに「面白い」の定義に依存します。

関連情報