web-dev-qa-db-ja.com

シェルスクリプトで正規表現を使用するにはどうすればよいですか?

シェルスクリプトで文字列を正規表現と一致させようとしています。この文字列はスクリプトのパラメーター($ 1)であり、日付(MM/DD/YYYY)です。使用しようとしている正規表現は次のとおりです。

^\d{2}[\/\-]\d{2}[\/\-]\d{4}$

動作しているようで、いくつかの正規表現テストWebサイトで試しました。

私のシェルコードは次のとおりです。

REGEX_DATE="^\d{2}[\/\-]\d{2}[\/\-]\d{4}$"
 
echo "$1" | grep -q $REGEX_DATE
echo $?

「エコー$?」パラメータに入力する文字列に関係なく、1を返します。

アイデアはありますか?

ありがとう!

20
Jérôme G

私はこれがあなたが望むものだと思う:

REGEX_DATE='^\d{2}[/-]\d{2}[/-]\d{4}$'

echo "$1" | grep -P -q $REGEX_DATE
echo $?

-Pスイッチを使用してPerlの正規表現を取得しました。

13
Chris Lear

既存の役立つ回答を補完するには:

Bash独自の正規表現一致演算子=~を使用することは、変数に既に格納されている単一の値とのみ一致する場合、この場合のより高速な代替手段です。

set -- '12-34-5678' # set $1 to sample value

kREGEX_DATE='^[0-9]{2}[-/][0-9]{2}[-/][0-9]{4}$' # note use of [0-9] to avoid \d
[[ $1 =~ $kREGEX_DATE ]]
echo $? # 0 with the sample value, i.e., a successful match

ただし、\dなどのフレーバー固有の正規表現構造を使用する場合は同様に適用されます:ただし、=~はERE(extended正規表現)、ホストプラットフォーム固有の拡張機能もサポートしています-これは、プラットフォームに依存するBashの動作のまれなケースです。

(Bashのコンテキストで)移植性を保つには、 POSIX ERE 仕様に固執します。

=~では、キャプチャグループ(かっこで囲まれた部分式)を定義することもでき、その一致は後でBashの特別な${BASH_REMATCH[@]}配列変数を介してアクセスできます。

詳細なメモ:

  • $kREGEX_DATEが使用されますunquoted。正規表現がそのように認識されるために必要です(引用された部分はliteralsとして扱われます)。

  • 必ずしも必要ではありませんが、Bashは\を含む正規表現literalsに問題があるため、最初に正規表現を変数に格納することをお勧めします。

    • たとえば、\<はWordの境界に一致するようにサポートされているLinuxでは、[[ 3 =~ \<3 ]] && echo yesは機能しませんが、re='\<3'; [[ 3 =~ $re ]] && echo yesは機能します。
  • 名前がすべて大文字の名前にならないように、変数名REGEX_DATEkREGEX_DATE((概念的な)定数を通知するk)に変更しました- 特殊な環境変数およびシェル変数との競合を防ぐために、すべて大文字の変数名は使用しないでください

44
mklement0

問題は、grepでサポートされていない正規表現機能を使用しようとしていることです。つまり、\dは機能しません。代わりにこれを使用してください:

REGEX_DATE="^[[:digit:]]{2}[-/][[:digit:]]{2}[-/][[:digit:]]{4}$"
echo "$1" | grep -qE "${REGEX_DATE}"
echo $?

-Eスタイルを使用するには、取得する{#}フラグが必要です [〜#〜] ere [〜#〜]

6
Mike Frysinger