今回もgrepの続きです。xxxにマッチさせたいけど正規表現でどう書く?というようなパターンについて簡単に説明していきます。
さて、今回もデスクトップのsampleディレクトリにサンプルとなるテキストファイルを入れておきます。また、カレントディレクトリはsampleディレクトリとします。コマンドならcd ~/Desktop/sampleです。今回は前回に引き続いてsample2.txtを使っています。
sample2.txt(※表示ではスペースになっていますが、実際はタブ区切りです。viでは:%s/ /\t/gで置換できます)
test data 2022/2/22
abTest1 50 $1.2
abTest2 45 $1.1
abTest3 98 $3
abtest4 30 $0.7
abtest5 14 $0.35
bbTest06 100 \1
bbTest07 200 \2
cbTest08 400 \4
cbTest09 999 \9
ddTest01 1024 12yen
ddTest02 4096 240yen
ddTest02 256 240yen
yenTest01 987 128
yenTest02 215 880yen
yenTest02 314 128Yen
yenTest03 2718 128YEN
○数値にマッチする正規表現
前回は数値にマッチする正規表現を使いましたが、{}は単純な個数指定だけでなく個数の範囲も指定できます。先ほどは4桁の数値にマッチするよう以下のように書きました。
grep -E '[0-9]{4}' sample2.txt
ここでマッチする桁を2桁から3桁にするなら{4}を{2,3}のように指定します。つまり{}の中に数字を書くと直前の文字等の個数を指定できます。
grep -E '[0-9]{2,3}' sample2.txt
{}は指定した個数以上を指定することもでき、この場合は個数の後に,を指定します。
grep -E '[0-9]{4,}' sample2.txt
5桁以上にマッチさせる場合は以下のようになります。該当するデータはないので何もマッチせず何も出力されません。
grep -E '[0-9]{5,}' sample2.txt
○Perl拡張表現
ここからはPerl拡張表現を使う場合です。macOSのgrepではオプションなしでも数値を示すメタ文字として\dが使えるので、ここまでのコマンド例は以下のように書き換えるだけで動きます。
grep -E '[0-9]{4}' sample2.txt ↓ grep -E '\d{4}' sample2.txt
Linuxなどの場合は-Pを指定します。
grep -E '[0-9]{4}' sample2.txt ↓grep -P '\d{4}' sample2.txt
○先頭・末尾の文字にマッチ
次にyenの文字を含む行を検索してみます。この場合部分一致になるのでyenを含む行が表示されます。
grep 'yen' sample2.txt
ここで先頭の文字がyenで始まる行だけを取り出したいとします。先頭が特定の文字で始まる時に何らかの処理をしたい場合は結構あります。最初が全角空白(日本語文章での字下げ)やマークダウンによる記述等での■などの記号で始まる文章は結構たくさんあります。データでも温度であれば氷点下の場合のみ取り出す(-記号の場合のみ取り出す)といった具合です。
grepで行の先頭文字にマッチさせるには^を指定します。以下のようにするとyenで始まる行だけがマッチします。
grep '^yen' sample2.txt
最後がyenで終わっている行は表示されていません。
grep 'yen$' sample2.txt
それならyenで始まってyenで終わる文字は以下のようにすればマッチする気もしますが、この場合は完全一致になるのでどの行もマッチせず何も表示されません。
grep '^yen$' sample2.txt
そこで、新たなメタ文字を使いましょう。yenで始まってyenで終わる場合は*を使います。1文字を示す.と組み合わせます。
grep '^yen.*yen$' sample2.txt
大文字と小文字を区別したくない場合は以下のようにオプションでiを指定します。
grep -Ei '^yen.*yen$' sample2.txt
○文字にマッチする個数
先頭がyenで始まって最後もyenで終わる行の場合は途中にいくつかの文字が含まれています。つまり途中に何らかの文字が含まれていることを示す必要があります。この場合、明確に個数を指定する方法と0個以上を指定する、1個以上を指定するなどの方法が用意されています。
何らかの文字が0個以上含まれている場合は*を指定します。以下のようにするとyenyenやyen012yenなどの文字列にマッチします。
test1.txt
yenyen
yen1yen
yen12yen
yen99999yen
1yen
2yen9yen
2yen9yen8
grep '^yen.*yen$' test1.txt
0個ではなく1個以上の場合は+を指定します。+を使用する場合はEオプションを付けないと期待通りに動作しません。以下のようにするとyenyenにはマッチしませんがyen012yenなどの文字列にはマッチします。
grep -E '^yen.+yen$' test1.txt
ここで.ピリオド(ドット)を含む行だけを検索するには以下のようにバックスラッシュでエスケープする必要があります。.ピリオド(ドット)はメタ文字なのでバックスラッシュを付けないと期待通りの結果になりません。
grep '\.' sample2.txt
○アルファベットにマッチ
アルファベットにマッチさせる場合は[ ]の中にマッチさせたいアルファベットを指定します。例えば小文字のaとeにマッチさせるには以下のように指定します。
grep '[ae]' sample2.txt
aeTにマッチさせるには以下のように指定します。
grep '[aeT]' sample2.txt
こんな感じでマッチさせたいアルファベットを書いていけばよいのですが、aからzまでマッチさせる場合は26文字全部書くのは面倒です。そこで数字のマッチの時にも出てきた範囲指定する-記号を使うと簡単になります。aからzまでマッチさせるには以下のように指定します。
grep '[a-z]' sample2.txt
○異なる複数の文字にマッチさせる
aからzのように範囲で決めることができる場合は-を使えば簡単ですが、範囲を指定できない関連性の低い文字にマッチさせたい場合もあります。
このような場合は[ ]の中にマッチさせたい文字を,で区切って書きます。つまりaとgとxとyとzのいずれかの1文字にマッチさせる場合は以下のようになります。
grep '[a,g,x,y,z]' sample2.txt
○気温が氷点下の場合だけリストアップする
何となく正規表現が使えるかもしれない気分になったところで気温データを使って検索してみましょう。
ここでは1ヶ月間の最低気温データから氷点下の場合のみリストアップしてみましょう。気温データは以下のように日付と気温になっておりそれぞれのデータは,で区切られています。つまりCSV形式のデータです。ヘッダーはありません。
data.txt
2023/2/1,-2.4
2023/2/2,-4.0
2023/2/3,-1.5
2023/2/4,0.6
2023/2/5,1.9
2023/2/6,3.4
2023/2/7,1.0
2023/2/8,-0.8
2023/2/9,-4.3
2023/2/10,-12.5
2023/2/11,-14.0
2023/2/12,-10.5
2023/2/13,-6.3
2023/2/14,-2.2
2023/2/15,0.7
2023/2/16,1.5
2023/2/17,2.1
2023/2/18,0.6
2023/2/19,-1.3
2023/2/20,0,4
2023/2/21,1.1
2023/2/22,2.9
2023/2/23,4.2
2023/2/24,5.7
2023/2/25,3.1
2023/2/26,5.8
2023/2/27,2.5
2023/2/28,-0.2
氷点下の場合のみピックアップすればいいので、単純にマイナスが含まれる文字を検索するように指定するだけです。
grep '-' data.txt
氷点下の日が何日あるか知りたい場合はwcコマンドと組み合わせます。以下のようにします。
grep '-' data.txt | wc -l
逆に氷点下ではない日をリストアップするにはvオプションを指定します。
grep -v '-' data.txt
日数を知りたい場合は先ほどと同様にwcコマンドを使います。
grep -v '-' data.txt | wc -l
日数を確認するには月の日数から氷点下の日数を引くという方法もあります。この計算を行う場合、exprを使います。grepとwcコマンドの実行結果を利用するので必要とするパラメータ部分はバッククオートで囲みます。
expr 28 - `grep '-' data.txt | wc -l`
.











![[USBで録画や再生可能]Tinguポータブルテレビ テレビ小型 14.1インチ 高齢者向け 病院使用可能 大画面 大音量 簡単操作 車中泊 車載用バッグ付き 良い画質 HDMI端子搭載 録画機能 YouTube視聴可能 モバイルバッテリーに対応 AC電源・車載電源に対応 スタンド/吊り下げ/車載の3種類設置 リモコン付き 遠距離操作可能 タイムシフト機能付き 底部ボタン 軽量 (14.1インチ)](https://m.media-amazon.com/images/I/51-Yonm5vZL._SL500_.jpg)