0

sed – – – 正規表現:マッチング→最長一致、最短一致 についての考察 – – –

sedの最短一致、sedの正規表現のマッチングの小技的なものをメモとして書いておく。

その前に基本をおさえます。

cat before.txt | sed -e 's/before/after/gi'
sed -e 's/before/after/gi' begore.txt

beforeをafterに変換。
gは全部変換。
iは大文字小文字無視。
-e はいくつでも繋げられる。
マッチした文字列の利用

beforeの部分で、\(と\)でくくると、afterの部分で\1で取り出せる。
beforeで複数\(\)を使うと、afterで\2\3\4な感じで抽出。つまり

$ echo 'abcdefghijklmn' | sed -e "s/.*\(d.*g\).*\(l.*$\)/\1\n\2/g"
defg
lmn

本日のお題:正規表現での最長一致のマッチング特性について考える。
■ HTMLをパースする場合を考える。
例えば、

<tr><td>id</td><td>data</td></tr>
<tr><td>1</td><td>DJKENTARO</td></tr>
<tr><td>2</td><td>MITSU THE BEATS</td></tr>
<tr><td>3</td><td>UPDEEPDJ</td></tr>

のようなデータからHTMLタグだけを消して、実データだけを抽出したいとする。
つまり、

id data
1 DJKENTARO
2 MITSU THE BEATS
3 UPDEEPDJ

のような結果を得たい!とする。
このときに、

sed s/\<.*\>//g DJs.html

みたいな書き方をすると悲しいことになる。(行全体にマッチしてしまい、すべて空行になってしまう。)
これは、複数のマッチングが考えられる場合なるべく長いものにマッチする(最長一致)からである。
この性質はsedに限ったことではなくて正規表現全般に言えることで、デフォルトでは最長一致である。

最短一致を利用するためのオプションを持つ言語もあるが、
sedには無いので何らかの工夫が必要となる。
今回の場合は、閉括弧が現れた時点で一旦マッチングをやめるようにすればいいので、以下のように書くと思惑のデータが抽出できる。

sed s/\<[^\>]*\>//g DJs.html

データの間にスペースを入れたい場合は、

sed 's/<[^>]*>/ /g' DJs.html

とする。(スペースを用いるので”で第一引数を囲む。”を使うとエスケープ文字の扱いが変わるので<>はエスケープしない。*注* )

*注*
シングルクオーテーションで囲んだ場合、シングルクオーテーション以外の文字は普通の文字と同じ扱い。ダブルクオーテーションで囲んだ場合は、”$`\以外の文字は普通の文字と同じ扱いになります。

それと最近知ったけど、sedはstream editorの略らしい。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です