web-dev-qa-db-ja.com

Bash ifステートメントでの正規表現の一致

ここで何を間違えましたか?

スペース、小文字、大文字、または数字を含む文字列と一致させようとしています。特殊文字もニースで​​すが、特定の文字をエスケープする必要があると思います。

TEST="THIS is a TEST title with some numbers 12345 and special char *&^%$#"

if [[ "$TEST" =~ [^a-zA-Z0-9\ ] ]]; then BLAH; fi

これは明らかに、上限、下限、数字、スペースのみをテストします。しかし動作しません。

* UPDATE *

もっと具体的にすべきだったと思う。これが実際の実際のコード行です。

if [[ "$TITLE" =~ [^a-zA-Z0-9\ ] ]]; then RETURN="FAIL" && ERROR="ERROR: Title can only contain upper and lowercase letters, numbers, and spaces!"; fi

* UPDATE *

./anm.sh: line 265: syntax error in conditional expression
./anm.sh: line 265: syntax error near `&*#]'
./anm.sh: line 265: `  if [[ ! "$TITLE" =~ [a-zA-Z0-9 $%^\&*#] ]]; then RETURN="FAIL" && ERROR="ERROR: Title can only contain upper and lowercase letters, numbers, and spaces!"; return; fi'
56
Atomiklan

Bashの[[ ]]構造について知っておくべき重要なことがいくつかあります。最初:

[[]]の間の単語では、単語の分割とパス名の展開は実行されません。チルダ展開、パラメータおよび変数展開、算術展開、コマンド置換、プロセス置換、および引用符の削除が実行されます。

2番目のこと:

追加の二項演算子 '=〜'が使用可能です......演算子の右側の文字列は拡張正規表現と見なされ、それに応じて一致します... パターンの任意の部分を強制的に引用できます文字列として一致させます

その結果、$vの両側の=~はその変数の値に展開されますが、結果はWord分割またはパス名展開されません。言い換えると、左側で変数の展開を引用符で囲まずに完全に安全ですが、右側で変数の展開が行われることを知っておく必要があります。

したがって、[[ $x =~ [$0-9a-zA-Z] ]]と書くと、右側の正規表現内の$0は、正規表現が解釈される前に展開され、おそらく正規表現のコンパイルに失敗します($0の展開がアスキー値の数字または句読記号で終了しない限り)桁未満です)。 [[ $x =~ "[$0-9a-zA-Z]" ]]のような右側を引用すると、右側は正規表現ではなく通常の文字列として扱われます(そして$0は引き続き展開されます)。この場合、本当に必要なのは[[ $x =~ [\$0-9a-zA-Z] ]]です

同様に、[[]]の間の式は、正規表現が解釈される前に単語に分割されます。そのため、正規表現内のスペースはエスケープまたは引用符で囲む必要があります。文字、数字、またはスペースを一致させたい場合は、[[ $x =~ [0-9a-zA-Z\ ] ]]を使用できます。 #のような他の文字も同様にエスケープする必要があります。もちろん、パターンを変数に入れることができます:

pat="[0-9a-zA-Z ]"
if [[ $x =~ $pat ]]; then ...

Bashの字句解析プログラムを通過するためにエスケープまたは引用する必要がある多くの文字を含む正規表現の場合、多くの人がこのスタイルを好みます。しかし、注意してください:この場合、変数展開を引用することはできませんcannot

# This doesn't work:
if [[ $x =~ "$pat" ]]; then ...

最後に、あなたがやろうとしていることは、変数に有効な文字のみが含まれていることを確認することだと思います。このチェックを行う最も簡単な方法は、無効な文字が含まれていないことを確認することです。つまり、次のような式:

valid='0-9a-zA-Z $%&#' # add almost whatever else you want to allow to the list
if [[ ! $x =~ [^$valid] ]]; then ...

!はテストを無効にして「一致しない」演算子に変換し、[^...]正規表現クラスは「...以外の任意の文字」を意味します。

パラメータ拡張演算子と正規表現演算子の組み合わせにより、bashの正規表現構文を「ほとんど読みやすい」ものにすることができますが、まだいくつかの落とし穴があります。 (常に存在しませんか?)1つは、]が引用されていても、$valid$validに入れることができなかったということです。 (これはPosix正規表現ルールです。文字クラスに]を含める場合は、先頭に移動する必要があります。-は先頭または末尾に移動できます。したがって、]-の両方が必要な場合は、 ]で終わり、-で終わり、正規表現「リードしてます」「絵文字:[][-]

133
rici

誰かが変数を使用した例を望んだ場合...

#!/bin/bash

# Only continue for 'develop' or 'release/*' branches
BRANCH_REGEX="^(develop$|release//*)"

if [[ $BRANCH =~ $BRANCH_REGEX ]];
then
    echo "BRANCH '$BRANCH' matches BRANCH_REGEX '$BRANCH_REGEX'"
else
    echo "BRANCH '$BRANCH' DOES NOT MATCH BRANCH_REGEX '$BRANCH_REGEX'"
fi
13
Oliver Pearmain

そのために[:punct:]を使用したいと思います。また、a-zA-Z09-9[:alnum:]になります:

[[ $TEST =~ ^[[:alnum:][:blank:][:punct:]]+$ ]]
10
konsolebox