1. ホーム
  2. スクリプト・コラム
  3. リナックスシェル

シェルファジー・マッチングとレギュラー・ディテール

2022-02-08 04:35:20

まえがき

正規では、ipアドレスが正規かどうかの検出、ファイル名が正規かどうかの検出など、簡単な関数を実装し、スクリプトで使用することができる。

正規表現

正規表現は、主に構文ルールのパターンを記述するために使用されます。実際、平たく言えば、文字とメタキャラクタの組み合わせを使って、与えられた構文にマッチするいくつかのパターンをファジーマッチさせるものである。主な機能は、テキストクエリと文字列操作です。

正規表現の基本要素には、通常の文字とメタキャラクタがあります。Linuxのシェル内部では、一般的な正規表現のメタキャラクタの集合は S={* .  ^ $ [] ୧୧⃛(๑⃙⃘◡̈๑⃙⃘) \{n,\} \{n,m} }のように、それぞれのメタ文字は正規表現において以下のような意味を持ちます。

記号:0回以上前の共通文字にマッチすることを意味します。これは正規文字であることに注意してください。つまり、JO*Bであれば、*は"JO"の文字列ではなく、任意の回数だけ"O"の文字にマッチすることを意味します。

記号:任意の1文字にマッチすることを意味します。次に " . " という文字は、任意の 1 文字を表します。例えば、文字列 . .73 は、最初の3文字が任意の文字(スペースを含む)であり、4文字目と5文字目がそれぞれ7と3であることを意味します。

記号:行頭のマッチングを示します。例えば、^cloud は、cloud という文字列で始まるすべての行にマッチすることを意味する。上記の1文字にマッチするのとは異なり、ここでは、その後に続く文字列全体にマッチする。

記号:行末に一致することを意味します。例えば、cloud$は、cloudという文字列で終わるすべての行にマッチすることを意味します。上記の行頭のマッチングと組み合わせると、^$は空の行にマッチすることを意味します。

記号:角括弧内の文字セットのいずれかに一致することを意味します。例えば、0-9の数字であれば、[0-9]という式を満たします。注意すべきは、^が[]の中に置かれたとき、^はもはや行頭を示さず、その逆を示すことである。例えば、[^7-9]は、7-9に含まれないすべての数字が式を満たすことを意味する。

記号:エスケープ文字です。正規表現の中にメタ文字が含まれていて、それを通常の文字として使いたい場合は、その前にエスケープ記号 " \ " を付けなければならない。例えば、「♪」は、正規文字「♪」を意味します。

記号:" \>" 内の文字が完全に一致することを示し、" \" を使用して <> の両文字をエスケープします。例えば \完全一致のため、"the", "theory"を含む行にはマッチしません。

記号:" * と同様に、その前に何回でも文字があることを意味します。しかし、" \{}"は繰り返しの回数を指定できます。例えば、 \{3} は前の文字を3回繰り返す、 \{3,\} は前の文字を3回以上繰り返す、 \{3,5} は3~5回繰り返すを意味します。例えば、 \JO{3}B は文字Oを3回繰り返す、すなわちJOOOBを意味し、 \JO{3,\}B はOを少なくとも3回繰り返す、すなわちJOOOB、JOOOOB などはすべて一致し、 \{3,5} はJOOOB、JOOOOB、JOOOOOBの文字列に一致します。

ワイルドカード

正規表現とワイルドカードを初めて知ったとき、どのタイミングで正規表現を使うのか、どのタイミングでワイルドカードを使うのか、戸惑いました。実は、システムにログインした後、bashシェルは正規表現をサポートしていません。つまり、bashシェルでいくつかのコマンドを正規表現で使っても、シェルがそれを認識せず、grep, sed, awkなどのツールを使って初めて有効になることがあるのです。そのため、bashシェルをファジーマッチング目的で使用する場合は、ワイルドカードを使用する必要があるのです。

ワイルドカードは、正規表現のメタ文字の一部、共通メタ文字の集合を使用します。E={? * [] {} ^ }. しかし、このワイルドカードのメタキャラクタの意味は、正規表現の内部と全く同じではありません。例えば

は、前の文字に何度でもマッチするという意味ではなく、任意の位置の任意の文字にマッチするという意味になります。例えば、phi * ip とすると、先頭にphiが3文字、最後にipが2文字で、philip、phillip、philsaip などにマッチすることになります。例えば ls -l *.awk は .awk で終わるすべてのファイルにマッチすることを意味し、* は任意の長さの任意の文字の組み合わせとなります。

は、任意の1文字のみを表します。正規表現のメタキャラクタである " . " と同じです。

quot; {}"文字はエスケープする必要がありません。は式の集合を表します。例えば、ls -l {[a-h]*.awk,0?.pem} は a-h 文字で始まるすべての .awk ファイルと 0 の後に任意の文字が続く .pem ファイルをリストアップします。

また、" ^ "文字は、行頭を示すのではなく、その逆を表します。

正規表現とワイルドカードはやや異なる文脈で使用されますが、どちらもファジーマッチングを実現することができます。正規表現はファイルの検索や、後述する grep、sed、awk などのツールを使った様々な操作でより有用です。

 例

ファイル名の仕様適合性を検出する。

#! /bin/bash

RED='\033[31m'
GREEN='\033[32m'

awk '{printf("%s",$0)}' $1 | egrep "^#[[:digit:]]*-(docs|unittest|pseudocode|msg-[^ ]. *)$" > /dev/null 2>&1

if [ $? -ne 0 ];then
 echo -e "message check ${RED}fail${NORMAL}"
 exit 1
fi
 echo -e "message check ${GREEN}success${NORMAL}"
exit 0



もちろん、ifを使うことも可能で、例えば

if [[ $1 =~ ^[0-9]+$ ]]; then
  echo "Is Number."
else
  echo "No Number."
fi


ipアドレスが指定に一致するかどうかを検出します。

テストファイルip.txtの構築

10.1.1.1
192.168.0.1
192.168.0.101
255.255.255.255
999.0.0.1
1.0.0.500
a.0.0.0
0.b.0.0
1.1.1
2.2
1
0.0.0.0

基本的な考え方は、各ポイントの間の要素を整数、最大3つの整数 [0-9]\{1,3} とし、.NETを使用します。それをつなぎ合わせて、さらに細かくマッチを制限するために^と$を追加する

cat ip.txt |grep '^[0-9]\{1,3\}\. [0-9]\{1,3\\}\. [0-9]\{1,3\}\. [0-9]\{1,3\\}$'


その結果は

10.1.1.1
192.168.0.1
192.168.0.101
255.255.255.255
999.0.0.1
1.0.0.500
0.0.0.0

ここでは精度が十分ではないので、整数を厳密に1-255に制限する必要がある(最初の要素は0にできない、後の要素は0にできる)、つまり、0-9 10-99 100-199 200-249 250-255

\([1-9]\|[1-9][0-9]\|1[0-9][0-9]\|2[0-4][0-9]\|25[0-5]\)     なお、|と()はエスケープされ、|で分割された要素は()で囲む必要がありますが、-E引数に拡張正規形が指定されている場合は \ でエスケープされないことに注意してください。

次に、次の3つの要素は、範囲を0-255に変更することで単純にスプライシングされます。

コピーコード コードは以下の通りです。
cat ip.txt |grep '^\([1-9]\|[1-9][0-9]\|1[0-9][0-9]\|1[0-9][0-9]\|2[0-4][0-9]\|25[0-5]\)\. \([0-9]\|[1-9][0-9]\|1[0-9][0-9]\|2[0-4][0-9]\|25[0-5]\)\. \([0-9]\|[1-9][0-9]\|1[0-9][0-9]\|2[0-4][0-9]\|25[0-5]\)\. \([0-9]\|[1-9][0-9]\|1[0-9][0-9]\|2[0-4][0-9]\|25[0-5]\)$'

結果は以下の通りです。

10.1.1.1
192.168.0.1
192.168.0.101
255.255.255.255

より簡潔な書き方はもちろん、覚えておくと便利です。末尾のメタは()で囲むこと

コピーコード コードは以下の通りです。
cat ip.txt |grep '^\([1-9]\|[1-9][0-9]\|1[0-9][0-9]\|2[0-4][0-9]\|25[0-5]\)\(\. \([0-9]\|([1-9][0-9]\|1[0-9][0-9]\|2[0-4][0-9]\|25[0-5]\)\)\{3\}$'

この記事では、シェルファジー・マッチングとルールについてご紹介します。シェルファジー・マッチングとルールについては、Script Houseの過去の記事を検索するか、下記の関連記事を引き続き閲覧してください。