nikkie-ftnextの日記

イベントレポートや読書メモを発信

grepの-oや正規表現の肯定先読み・肯定戻り読みで、テキストの一部だけを取り出す

はじめに

種田梨沙さん、お誕生日おめでとうございます。
Act-4を思い出して、うう。。😭1 nikkieです。

grep正規表現まわりで最近の学びです

目次

grep -o

大変お世話になっているgrep

マスタリングLinuxシェルスクリプト 第2版』より(8.1)

grep(global regular expression print)、すなわち私たちが一般的にgrepコマンドと呼んでいるものはコマンドラインツールの1つであり、検索をグローバルに(つまり、ファイル内のすべての行について)行い、その結果を標準出力STDOUTに出力します。
検索文字列として正規表現を使います。

検索文字列に一致する部分のある行を出力できます

今回-oを知りました。
これは--only-matchingの略。
一致した部分だけを取り出します2

% cat example.txt
boto3           1.26.59
botocore        1.29.59
% grep boto example.txt
boto3           1.26.59
botocore        1.29.59
% grep -o boto example.txt  # 一致する部分のみ!
boto
boto

肯定先読み

検索文字列に「肯定先読み」なるものが使えることを知りました。

grep -Pと一緒に使います。
なおmacOSのデフォルトのgrep-Pをサポートしていませんでした。
GNU grepbrew install grepしてggrepを使います。

正規表現辞典 改訂新版』(03-07-02)を参考にした例

% cat files.txt
sample1.doc
example2.txt
sample3.log

(?=pattern)patternが右(=先)に存在する場合にマッチします。
grep -P--perl-regexp(検索文字列をPerl互換正規表現として扱う)

% ggrep -P '.*(?=\.doc|\.txt|\.log)' files.txt
sample1.doc
example2.txt
sample3.log

grep -oと組み合わせると、拡張子を除いて取り出せます3

% ggrep -oP '.*(?=\.doc|\.txt|\.log)' files.txt
sample1
example2
sample3

肯定戻り読み

肯定先読み(右を見る)とは逆に、を見るのが「肯定戻り読み」。
正規表現辞典 改訂新版』では03-07-04です。

これらを知るきっかけとなったのが以下のようなファイル。
ログファイルのうち識別子(ここでは拡張子を除いたファイル名)を取り出したいというシーンです。

% cat practical.txt
file= sample1.doc
file= example2.txt
file= sample3.log

肯定先読みだけだと

% ggrep -oP '.*(?=\.doc|\.txt|\.log)' practical.txt
file= sample1
file= example2
file= sample3

左側が残ります(.*は左側にもマッチしているため)。
ここに肯定戻り読み(?<=pattern)も合わせると

% ggrep -oP '(?<=file= ).*(?=\.doc|\.txt|\.log)' practical.txt
sample1
example2
sample3

拡張子を除いたファイル名が取り出せました!

終わりに

学びのまとめです

  • grep-oでマッチする部分だけを取り出せる
  • grep -Pで、肯定先読み(?=pattern)・肯定戻り読み(?<=pattern)が使える
  • これらを使って、テキスト中からほしい部分を取り出した(ログ中のファイル名を例に)

いずれも知らなかったのですが、GitHub Copilotに入力と期待出力を与えて、コマンドを生成させる中で知りました。

Copilotと戯れるイメージ

# 入力

file= sample1.doc
file= example2.txt
file= sample3.log

# 期待出力

sample1
example2
sample3

# コマンド


  1. 私の瞳もSing a Wing Song
  2. このブログをgrepで検索して見つかった例を再利用しています
  3. Pythonのドキュメントの語彙を使うと stem です。 https://docs.python.org/ja/3/library/pathlib.html#pathlib.PurePath.stem