« CODE COMPLETE 第2版 下 | トップページ | Sleipnir2カスタマイズテクニック »

2008年6月23日 (月)

bashスクリプトで正規表現

 

前書き

 

僕が正規表現をよく使うのは、vimで文字列の検索や置換をするときですが、たまにシェルスクリプトの中で使いたくなることがあります。そういう時普通はperlで書くのでしょうが、あいにく僕はperlがつかえない(orz)ので、毎回edやらgrepやらsedやらawkやらを調べて場当たり的に解決しています。で、この前、後輩に質問されて「う、こんな簡単なことなのにどうやったらいいのか分らないなんて!」とショックを受けたことがあったので、調査結果をメモっておきます。

 

問題

 

データを行毎に記録したテキストファイル(例:data.txt)がある。そのテキストファイルを1行ずつ読み取って、コマンドを実行したい。ただし、#で始まる行や空行は無視したい。

 

解答

 

exprコマンドは、正規表現を解釈する(!)ので、それを使う。

 
#!/bin/sh 
TARGET_FILE="data.txt" 
while read LINE 
do 
    if expr "$LINE" : "#" > /dev/null || [ -z "$LINE" ] 
    then 
        continue 
    else 
        echo "$LINE" 
    fi 
done < $TARGET_FILE

注意点は、exprの標準出力を/dev/nullに捨てることと、正規表現の先頭に暗黙のうちに"^"(行頭)が付加されること。

以下実行例:

[lucy@fedora7 regexp]$ cat data.txt 
one 
#two
four 
five 
six# 
se #ven

ten 
[lucy@fedora7 regexp]$ ./regexp.sh
one
four
five
six#
se #ven
ten

まとめ

exprで正規表現を扱えるとは知りませんでした。expr string : regexp もしくは expr match string regexp でもよいみたいです。標準出力にはマッチした文字数がでるみたいです。また、\( \)で囲ってある部分があれば、そこの文字列がでるそうな。詳細はこの辺で。

でもbashのfor文だと、行区切りではなくて、空白区切りでループされてしまうので、1行内にブランクがある場合はどうしたらいいんでしょね。これまたFAQの類だと思うんですが、また分ったら書きます。

というわけで、

while read LINE
do
:
done < $TARGET_FILE

構文(?)で修正したプログラムを載せてみました。

|

« CODE COMPLETE 第2版 下 | トップページ | Sleipnir2カスタマイズテクニック »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/207693/41618998

この記事へのトラックバック一覧です: bashスクリプトで正規表現:

« CODE COMPLETE 第2版 下 | トップページ | Sleipnir2カスタマイズテクニック »