複合コマンドでのbashオプションの設定


9

extglob複合化合物内でシェルオプションを設定すると、後続のアンチグロブが失敗することがわかりました。シェルオプションは、複合コマンドの外部で設定する必要がありますか?私はbashのmanページにそのような要件の兆候を見ませんでした。

例として、次のスクリプトは正常に機能します(prints a.0 a.1)。

#!/bin/bash
touch a.0   a.1 \
      a.b.0 a.b.1
shopt -s extglob
ls "a."!(b*)

ただし、最後の2行が複合コマンドとして実行されると、スクリプトは次のエラーで失敗します。

syntax error near unexpected token `('
`    ls "a."!(b*)'

これは、4.2から4.4までのbashバージョンを使用して、さまざまな複合コマンドでテストされました。

(1)条件付き- if

#!/bin/bash
touch a.0   a.1 \
      a.b.0 a.b.1
if true; then
    shopt -s extglob
    ls "a."!(b*)
fi

(2)ブレース- { }

#!/bin/bash
touch a.0   a.1 \
      a.b.0 a.b.1
{
    shopt -s extglob
    ls "a."!(b*)
}

(3)サブシェル- ( )

#!/bin/bash
touch a.0   a.1 \
      a.b.0 a.b.1
(
    shopt -s extglob
    ls "a."!(b*)
)

すべてのケースで、shoptが複合コマンドの外に移動された場合、スクリプトは成功します。

回答:


14

複合コマンドの一部は、コマンド全体が解析される前に実行されません。これは、マニュアルのシェル操作セクションに斜めに記載されています。すべてのトークン化と解析は、「the」コマンドが実行される前に行われます。有効にextglobすると、トークン化中に認識される新しいパターンマッチング演算子が追加され、言語構文が変更されます。

そのshopt時点でコマンドが実行されていないため、履歴の展開がないことを除いて、単一のアイテム(およびと同じ)などとしてではなく!(、試行された履歴の展開(!)または制御演算子として表示されます。そこ)。(!(@(

構文解析がそのトークンに到達すると、どちらの場合も通常はエラーになります!(...)が、行の先頭または後timeはサブシェルパイプラインが否定されます。「unexpected token `('」は、その場所でサブシェル式を受け入れることができなかったことを意味します。

サブシェルで一時的にのみextglobを有効にしたい場合、これはやや面倒です。回避策の一つは、再度無効extglob、あなたがしたいグロブを使用する関数を定義し、することですその後、有効extglobでサブシェルから関数を呼び出します:

shopt -s extglob
f() { ls "a."!(b*) ; }
shopt -u extglob
(
    shopt -s extglob
    f
)

とても不格好です。


複合コマンド内でエイリアスを作成した場合も、構文解析の前にエイリアスが処理されるため、同じ効果が発生します。

if true
then
    alias foo=echo
    foo bar
fi
foo xyz

印刷されfoo: command not found、その後xyz、エイリアスがあるためれるまで作成されますが、利用できませんif行われます。


ありがとう-複合コマンドが実行前に1つの単位として解析されることに気づかなかった。これで動作が意味をなすようになりました。
user001 2019年

3
@ user001私はそれが理にかなっていると言うのはそれほど慈善ではありません。解析中にレクサーのモード切り替えることは前代未聞のことではなく、他の言語のように、Cまたはperlそれをうまく行うことができます。複合コマンドの一部ではないことは十分ではなくshopt -s extglob、別の行にある必要があることに注意してください。また、説明と例を参照してくださいここに
mosvy

@mosvy:bashが複合コマンドを1つの単位として解析することに気づくと、観測された動作が意味をなすことを意味しました(パーサーの制限が必ずしも合理的ではない)。他の投稿での議論にリンクしていただきありがとうございます。
user001
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.