それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

正規表現あと読みと grep -o の組合せで強い文字列の抜き出しができる

正規表現にはあと読みの条件付きマッチの書式がある。

(?<=pattern)expression
expression(?=pattern)

このあと読みの条件マッチを使うことで、○○のあとの△のような文字をダイレクトに抜き出すことが可能になり、コマンドと組み合わせると非常に強いクカを得ることができる。

正規表現のあと読みをgrep で使うことが出来る。

この名前付きのマッチングをgrep で使うと便利そうなので、調べてみたら 私の使ってるgrep は対応してたので、実例を残すことにした。

grep を使った文字列の抜き出し

grepをつかってマッチした文字列をダイレクトに抜き出すことが出来ます。 その際に、マッチする箇所を限定することが出来て便利です。

grep -Poで抜き出し

たとえば、A のあとに続くIPアドレスが欲しい時

$ dig t.co | \grep -Po "A\s+\d.+$"
A    104.244.42.133
A    104.244.42.5
A    104.244.42.197
A    104.244.42.69

A も含めてIPアドレスが取れてしまう。

これを条件マッチでやると

正規表現を「 lookbehind assertion」(後置参照)に変えることで、きっちりマッチする。

$ dig t.co | \grep -Po "(?<=A\s)\d.+$"
104.244.42.133
104.244.42.5
104.244.42.197
104.244.42.69

lookbehind assertion (?<=XXX)は、正規表現に〇〇に続く△でこの場合は「Aのあとにある数字から始まる文字列」を指定している。

正規表現の条件で絞っている。

そのため名前付きマッチだとか正規表現の後方参照で $0 を取り出す必要もない。

面倒なことが少し減っている。

他の例

dig の結果からIPを抜き出す。

たとえば、dig をした結果から、IPアドレスを抜き出そうとする

$ dig _netblocks3.google.com txt +short | \grep -oP '(?<=ip4:)[0-9\.]+/[0-9]+'

-Po をつけた場合。

この結果は次のようになる。

172.217.0.0/19
172.217.32.0/20
172.217.128.0/19
172.217.160.0/20
172.217.192.0/19
172.253.56.0/21
172.253.112.0/20
108.177.96.0/19
35.191.0.0/16
130.211.0.0/22

単純な正規表現の場合

-Po をせずに、正規表現で抜き出すと、次のようになってしまう。

$ dig _netblocks3.google.com txt +short | \grep -oE '(?ip4:)[0-9\.]+/[0-9]+'
ip4:172.217.0.0/19
ip4:172.217.32.0/20
ip4:172.217.128.0/19
ip4:172.217.160.0/20
ip4:172.217.192.0/19
ip4:172.253.56.0/21
ip4:172.253.112.0/20
ip4:108.177.96.0/19
ip4:35.191.0.0/16
ip4:130.211.0.0/22

この結果を再度awk/sed して置換するのも面倒ですよね?

dig で spfレコードしらべて、TXTレコードからIPアドレス取り出すという作業ですら、grep だけで解決するのである。プログラミングしなくてもいいのは楽である。

他にもこのようなことに使える。

takuya@~$ sudo networksetup  -getairportpower en0
Wi-Fi Power (en0): On

この結果からen0のあとの ONだけを取出したい。

takuya@~$ sudo networksetup  -getairportpower en0  | env grep -Po '(?<=:)\s?\w+$'
 On

Macアドレスをコマンドの結果から取得したり。

takuya@~$ ifconfig en0 | env  grep -Po  '(?<=ether\s).+'
60:03:08:a1:82:0c

IPアドレスをしっかり抜き出したり。

takuya@~$ ifconfig en0 | env  grep -Po  '(?<=inet\s)[0-9\.]+'
172.24.49.119

慣れると便利。

慣れてくると割と便利に使うことが出来る。この文字の「ココだけが」ほしいんだけどなぁっていうときに、文字列が取れすぎるとか、絞り込めないときに知っておくと最後の一歩をすることが出来る。

今回つかった grepGNUのパッケージです。

takuya@work$ /Users/takuya/.bin/grep -V
grep (GNU grep) 3.1
Packaged by Homebrew
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.

一般的なLinuxなパッケージにも含まれています。 Linuxディストーションによっては、grep はalias されている場合があります。そのためalias があると上手く動かなったりするので、alias を解除してから試す必要があります。

参考資料

今回はこの書籍から正規表現を学びました。

2021-03-31

dig sfpで、TXTレコードの例を追加