最近は全然なのですが、元々AIXの仕事してました。
その時に結構お世話になっていたのですが、bashにはなかったのでなんとか実現できないかな、と試行錯誤しました。
- 目次 -
そもそもAIXのgrep -pって?
ちょっとマニアックなので知らない人も多いと思うので、まずマニュアルを引用しちゃいます。
-p[Separator] 一致する行を含むパラグラフ全体を表示します。パラグラフは、Separator パラメーターで指定された、 パラグラフ・セパレーターで区切られます。パラグラフ・セパレーターは検索パターンと同じ書式のパターンです。 パラグラフ・セパレーターを含んでいる行は、セパレーターとしてのみ使用され、出力には含まれません。デフォルトのパラグラフ・セパレーターはブランク行となります。
※IBMDocumentaionより
正直わかりづらいのですが、要するに検索した文字列を含むブロック(空行区切り)をまとめて出力してくれるオプションです。案外便利だったのですが、Linuxにはないようです。
とりあえず結論
grep でなくawkを使うと似たことができました。
とりあえずサンプルや実行例です。
awkでの構文
空行を区切りとして、検索した文字列の次の空行までを出力する
$ awk -v RS= '/検索したい文字列/' ファイル名
実行例
■sample.txt
2021/01/01
sample1
sample2
2022/01/02
SAMPLE1
SAMPLE2
2023/01/03
Sample
2024/01/04
Sample3
実行例① 2021を含むもの検索
$ awk -v RS= '/2021/' sample.txt
2021/01/01
sample1
sample2
シンプルに検索文字列を入れると次の空行までを出力します。
実行例② 1つのブロックの中の途中の文字列を検索
$ awk -v RS= '/SAMPLE/' sample.txt
2022/01/02
SAMPLE1
SAMPLE2
同一ブロックの途中の文字(SAMPLE)を検索すると、そのブロック全体が表示されます。
実行例③ 空行で区切られていない
$ awk -v RS= '/2024/' sample.txt
2023/01/03
Sample
2024/01/04
Sample3
区切りが空行のため、1つのブロックとして表示されます。
実行例④ 検索文字列を複数指定
$ awk -v RS= '/sample|SAMPLE/' sample.txt
2021/01/01
sample1
sample2
2022/01/02
SAMPLE1
SAMPLE2
「|」で区切ることで複数文字を検索できます。
オプションの意味
以下はオプションや動作の説明です。
-v
オプション
-v
は awk
のオプションで、スクリプトが実行される前に変数を設定するために使います。
$ awk -v RS= '/検索したい文字列/' ファイル名
今回はRS
(Record Separator)を空に設定しています。
RS
(Record Separator: レコード区切り)
RS
は awk
の特別な変数で、「レコード(行)」の区切りを決めるものです。
通常 RS
のデフォルト値は \n
(改行)を1行として処理しますが、これを空行に変更して扱うようにしています。
RS=
の動作
RS=
の場合、RS
を空文字 (""
) に設定することになります。
- 空行(複数の改行)で区切られたブロック単位で処理する
- 通常
awk
は1行ごとに処理しますが、RS=
を設定すると空行ごとにブロックとして処理します。 \n\n
(連続した改行)があると、それを1つのレコードの終端とみなす。
- 通常
これにより、ブロック単位で処理するように変更しています。
/検索パターン/
の動作
awk
のパターン /検索パターン/
は、そのブロック内に「検索パターン」が含まれるものを出力するという意味になります。
awk -v RS= '/SAMPLE/' file.txt
この場合、データのブロックの中に "SAMPLE"
という単語が含まれている場合、そのブロック全体を表示します。
出力例
$ awk -v RS= '/SAMPLE/' sample.txt
2022/01/02
SAMPLE1
SAMPLE2

コメント