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


89

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

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

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

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

これは明らかに、上部、下部、数値、およびスペースのみをテストします。しかし、動作しません。

*更新*

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

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

*更新*

./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'

実際に使用しているシェルはどれですか?/ bin / sh?/ bin / bash?/ bin / csh?
Willem Van Onsem 2013

8
正規表現を変数に入れる方が安全です。re='...whatever...'; [[ $string =~ $re ]](引用符なし-これは、引用符なしで機能する何かを壊すまれなケースの1つです)。
Charles Duffy 2013

3
代わりに、割り当てを一重引用符で囲んでください。二重引用符は特殊文字を適切に保護しません。
トリプリー2013

多くのthxチャールズ!変数に入れなくても大丈夫ですが、引用符で囲まないでください。例:[[ $var =~ .* ]]マッチ正規表現.*(すべて)の場合。私は...あなたが引用符を使用する場合、引用符自体は正規表現の一部とみなされていることを推測する
ステファン・

4
私が見つけた落とし穴の要約:(1。)単一引用符を使用して変数にパターンを保存するpattern='^hello[0-9]*$'(2.)正規表現のマッチングが必要な場合は、引用符で正規表現のパターンマッチングを無効にするため、パターンを引用しないでください(つまり、式[[ "$x" =~ $pattern ]]は正規表現を使用して一致し、式[[ "$x" =~ "$pattern" ]]は正規表現の一致を無効にし、と同等です[[ "$x" == "$pattern" ]])。
Trevor Boyd Smith

回答:


184

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

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

2番目のこと:

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

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

したがって、次のように記述した場合、右側の正規表現[[ $x =~ [$0-9a-zA-Z] ]]$0内部は、正規表現が解釈される前に展開されます。これにより、正規表現のコンパイルに失敗する可能性があります($0ASCII値がより小さい数字または句読記号で終了する場合を除く)。数字)。-soのように右側を引用すると、右側[[ $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のレクサーを通過するためにエスケープまたは引用符で囲む必要のある文字が多数含まれている正規表現の場合、多くの人がこのスタイルを好みます。ただし、注意してください。この場合、変数展開を引用することはできません

# 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の正規表現構文を「ほぼ読み取り可能」にすることができますが、まだいくつかの落とし穴があります。(いつもあるのではないですか?)一つは、引用さ]れた$validとしても、$valid最初を除いて、入れることができなかったということです。(これはPosixの正規表現ルールです。]文字クラスに含める場合は、最初に配置する必要があります。-最初または最後に移動できます。したがって、との両方が必要な場合は]-で開始し]て終了する必要があります-。正規表現につながる絵文字を「私は私がやっているか知っています」: [][-]


6
「!〜は「一致しない」演算子です」は正しくないことを指摘したいだけです。使用if ! [[ $x =~ $y ]]またはif [[ ! $x =~ $y ]]
アルコール

shellcheckerが同意しません...– SC2076: Don't quote rhs of =~, it'll match literally rather than as a regex.
Leonardo

4
@leonard:「変数展開を引用できません」という私のステートメントや「これは機能しません」というコメントとどう違うのですか?それについて何が不明確ですか?
rici 2016

1
@jinbeomhong:式自体は、通常どおり空白を使用して単語に分割されます。ただし、パラメーターとコマンドの展開は単語分割ではありません。
RICI

1
@jinbeomhong:bashのマニュアルと何も違うことは言っていません。「と」の間の単語は、コマンドラインが単語に解析されるのと同じ方法でプログラムテキストから解析されます。ただし、コマンドラインとは異なり、単語は展開後に分割されません。[[]]
RICI

30

誰かが変数を使用した例が必要な場合...

#!/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

[:punct:]そのために使いたいです。また、a-zA-Z09-9ちょうどかもしれません[:alnum:]

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

-1

または、私が行ったようにたまたまばかげたタイプミスをして、=〜を〜=に逆にしたので、この質問を見ているかもしれません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.