グローバルモードで文字通り「|」を処理しないでください。

グローバルモードで文字通り「|」を処理しないでください。

私の質問は以下から来ています。シェル変数に正規表現を格納してシェル固有の文字を引用する問題を回避するには?

  1. エラーが発生する理由:

    $ [[ $a = a|b ]]  
    bash: syntax error in conditional expression: unexpected token `|'
    bash: syntax error near `|b'
    

    [[ ... ]]2番目のオペランドは内部的に=ワイルドカードパターンであると予想されます。

    a|b有効なワイルドカードパターンではありませんか?どの文法規則に違反しているかを指摘できますか?

  2. 以下のコメントは|パイプとして解釈されることを示しています。

    その後、=globモードを=~正規表現モードに変更して|動作させます。

    $ [[ $a =~ a|b ]]
    

    私はそれから学んだ学習乱交p180インチ私の以前の投稿|他の解析ステップ(例の条件式解析を含む)の前にも、解析の開始時にパイプとして認識されます。それでは |、使用時に正規表現演算子として認識されますが、誤って=~使用された場合はパイプとして認識されないようにするにはどうすればよいですか=?これにより、パート1の構文エラーが|パイプとして解釈されるわけではないと思いました。

    シェルが標準入力またはスクリプトから読み取る各行はパイプと呼ばれ、ゼロ個以上のパイプ文字(|)で区切られた1つ以上のコマンドを含みます。読み取るパイプごとに、シェルはそれをコマンドに分割し、パイプのI / Oを設定した後、各コマンドに対して次のことを行います(図7-1)。

ありがとうございます。

ベストアンサー1

正当な理由はありません。

[[ $a = a|b ]]

$aが文字列かどうかをテストする代わりに、エラーを報告する必要があり、a|bwhileは[[ $a =~ a|b ]]エラーを返しません。

唯一の理由は|一般的に(外部的にも内部的に[[ ... ]])特殊文字であるからです。その[[ $a =場所にはbash通常のトークンタイプが必要です。言葉通常のシェルコマンドラインの引数またはリダイレクトターゲットと同じです(ただし、extglobbash 4.1以降のオプションが有効になっているかのように)。

(通過言葉ここで、私の言葉は言葉次の仮想シェル構文でPOSIX仕様で説明されているタイプシェルは、英語の文字列やスペース以外の文字列など、他の単語定義ではなく、単純なシェルコマンドラインのトークンに解析します。foo"bar baz"、、$(echo x y)これは2つです言葉S)。

一般的なシェルコマンドラインから:

echo a|b

.not aecho aにパイプされるba|b言葉、これは3つのマークです:a 言葉|トークン、b 言葉トークン。

使用するとき[[ $a = a|b ]]bash期待して下さい言葉()を取得しましaたが、予期しない|トークンを見つけてエラーが発生します。

興味深いことに、bash苦情はありませんでした。

[[ $a = a||b ]]

これでaトークン、||トークン、別のトークンがあるので、b次のように解析されます。

[[ $a = a || b ]]

文字列$aが空であることをテストします。ab

今:

[[ $a =~ a|b ]]

bash同じ構文解析ルールを持つことはできません。同じ構文解析ルールを使用すると、上記のエラーが発生し、ルールが単一であることを確認|するためにルールを参照する必要があることを意味します。a|b言葉。しかし、bash 3.2から始めると、次のようになります。

[[ $a =~ 'a|b' ]]

a|bこれはもはや正規表現の一致のためではありませんa\|b。つまり、シェル引用には正規表現演算子の特別な意味を排除する副作用があります。これは機能なので動作は[[ $a = "?" ]]似ていますが、ワイルドカードパターン(で使用されている[[ $a = pattern ]])はシェルです。性格(例:globで使用されます)正規表現の場合は該当しません。

bashしたがって、通常のような特殊なシェル文字であるすべての拡張正規表現演算子は、演算子引数を解析するときに|異なる方法で処理する必要があります()=~

しかし、参考にしてください。

 [[ $a =~ (ab)*c ]]

今有効です。

 [[ $a =~ [)}] ]]

いいえ。以下を行う必要があります。

 [[ $a =~ [\)}] ]]
 [[ $a =~ [')'}] ]]

以前のバージョンでは、bashバックスラッシュが間違って一致していました。この問題は解決しましたが、

 [[ $a =~ [^]')'] ]]

するいいえたとえば、バックスラッシュを一致させます。括弧内にbashあることがわかる方法がないため、エスケープを実行すると、およびを除くすべての文字に一致する正規表現が生成されます。))[^]\)]]\)

ksh93これに関して、より深刻なエラーがあります。

ではzsh一般的なシェル語なので、正規表現演算子を引用しても正規表現演算子の意味には影響しません。

[[ $a =~ 'a|b' ]]

正規表現と一致しますa|b

これは/コマンド=~にも追加できることを意味します。[test

[ "$a" '=~' 'a|b' ]
test "$a" '=~' 'a|b'

(..でも使用できます。特別なシェル演算子があるため、yashasとして引用する必要があります。)=~zsh=something

bash 3.1も同様に動作しました。 3.2では、おそらく(最初のシェル提案にもかかわらず)zsh一貫性を維持するために変更されていますが、それでも以前の動作を実行または元に戻すことができます(3.1でエラーを返す場合を除く)。最新バージョンで動作します)。ksh93bash[[ =~ ]]BASH_COMPAT=31shopt -s compat31[[ $a =~ a|b ]]bashbash -O compat31bash

私がこのルールが混乱していると言った理由と次のことを使用する理由が明確になることを願っています。

[[ $a =~ $var ]]

他のシェルを含む移植性に役立ちます。

おすすめ記事