bashで複雑な正規表現を操作する方法

bashで複雑な正規表現を操作する方法

アイデアは、URLの入力パターンの基本的なチェックを行うことです。

$ ns='abc.def.com'
$ reg_expr="\N*\.(\D{2}|\D{3})$"
$ echo $reg_expr
\N*\.(\D{2}|\D{3})$
$ [[ $ns =~ "$reg_expr" ]] && echo "ok" || echo "no"
no

しかし、正規表現は常に失敗します。同じパターンのオンライン正規表現チェックが正しく機能します。

https://regex101.com/r/vXxv1w/1

なぜこれが起こるのですか?

答え1

それ

\N*\.(\D{2}|\D{3})$

Perl 正規表現です。 bashの[[ =~ ]]演算子は、Perl正規表現ではなくPOSIX拡張正規表現を使用します。

Perl スタイルの正規表現を使用するには、zsh とそのrematchpcreオプションを使用します。

set -o rematchpcre
[[ $ns =~ '\N*\.(\D{2}|\D{3})$' ]]

今、この正規表現はあまり意味がありません。

  • \N改行を除くすべての文字と一致するように設計されていますが、フラグを設定しない限り()を使用して、改行sは一致しないために置き換えることができます。(?s).\N.
  • <anything>*一致するため、正規表現の始まりまたは終わりにあることは意味がありません。0またはmore<anything>なので、何も一致しません。[[ $ns =~ '\.(\D{2}|\D{3})$' ]]機能的に同じです。
  • \D10進数(例:0123456789または0123456789٠١٢٣٤٥٦٧٨٩0123356789ot German)を除くすべての文字と一致します。 ८ ८ ८ ০১২৩৪৫৬৭৮৯੦੧੨੩੪੫੬੭੮੯૦૧૨૩૪૫૬૭૮૯ ९ ୭ ୭ ൯ ෦෧෨෩෪෫෬෭෮෯ ๐๑๒๓๔๕๖๗๘๙໐໑໒໓໔໕໖໗໘໙༠༡༢༣༤༥༦༧༨ ๐๑๒๓๔๕๖๗๘๙໐໑໒໓໔໕໖໗໘໙༠༡༢༣༤༥༦༧༨ ༩၀၁၂၃၄၅၆၇၈၉႐႑႒႓႔႕႖႗႘႙០១២៣៤៥៦៧៨៩᠐᠑᠒᠓᠔ ᠕᠖᠗᠘᠙ ᠕᠖᠗᠘᠙ ᥆᥇᥈᥉᥊᥋᥌᥍᥎᥏ ᧑᧒᧓᧔᧕᧖᧗᧘᧙᪀᪁᪂᪃᪄᪅᪆᪇᪈᪉᪐᪑᪒᪓᪔᪕ ᪖᪗᪘᪙᭐ ᭑᭒᭓᭔᭕᭖᭗᭘᭙᮰᮱᮲᮳᮴᮵᮶᮷᮸᮹᱀᱁᱂᱃᱄᱅᱆᱇᱈᱉᱐᱑᱒᱓᱔᱕ ᱖᱗᱘᱙꘠꘡ ᱖᱗᱘᱙꘠꘡ KR 0123456789

答え2

のマニュアルページには、テストに有効な演算子をbash説明するいくつかの段落があります。[[ expression ]]正規表現のマッチングに関する記事では、次のように述べています。

==と!=と同じ優先順位を持つ追加の2項演算子=~を使用することもできます。使用すると、演算子の右側の文字列はPOSIX拡張正規表現として扱われ、それに応じて一致します。

(いくつかの文をスキップ)

パターンの一部が引用されると、引用された部分は文字通り一致します。これは、引用された部分のすべての文字が特別なパターンマッチングの意味なしにそれ自体でマッチすることを意味します。パターンがシェル変数に格納されている場合、引用変数拡張はパターン全体を文字通り一致させます。

要約すると、内部的に正規表現の周りに引用符を[[ expression ]]入れず、正規表現を含む変数の周りに引用符を入れないでください。=~正規表現を引用すると、比較演算子として指定しても比較が純粋な文字列一致に変わります==

どの正規表現構文がサポートされているかについては、マニュアルページの参照に従ってください。[[:digit:]]andの[^[:digit:]]代わりに\dandを使用することもできます\D。 (間違っている可能性があるので、自分で確認してください)

関連情報