Linuxで文字列を操作しデータを整形する方法について、各手法の特性や基本的な文法などを確認する。
今回はperlについて。
#■perlについて
perlは文字列処理に優れる汎用のインタプリタ型プログラミング言語であり、多くのLinux環境でデフォルトで利用できる。
オプションを指定することで、ワンラインでawkやsedのような文字列処理を行なうことができ、幅広く使用できる。
$ echo 'good morning' | perl -pe 's/morning/evening/g'
good evening
前回の記事のex1と同じように
入力文字列'good morning'に対して'morning'を'evening'に置換する処理を行っている。
詳しくは後述するが、-eオプションの後にperlスクリプト文を記述し、ワンライナーとして処理を実行している。
前回のsedでのコマンド文と、スクリプト部分についてはほぼ同じ(むしろ今回の例では全く同じ)になっていることがわかる。
今回は、ワンラインコマンドとしての構造とオプションの解説を最初に行い、ex1のようなsed的文字列操作と、別のオプションを用いたawk的な文字列操作について、それぞれ学習していく。
#■構造
perl [-オプション] '[スクリプト]' ([入力ファイル])
(ワンラインコマンドとしての)perlコマンドの実行は上記の形になる。
なお、後述するがワンラインコマンドとして実行する際は-eオプションを指定しなければならない。
perl自体の文法などについては今回は割愛し、文字列操作の流れのみを扱う。
#■オプション
・-e
与えられた文字列をスクリプトとして実行する。
なお、-eはコマンドオプション中最後尾に指定しなければ
他のオプションが正常に動作しない。
・-p,-n
入力データを各行ごとに処理する。
-pは処理後に出力され、-nは出力を行わない。
・-l
行ごとに処理を行う際に、入力文字列末尾の改行コードを削除して取り扱う。
また、出力時には行ごとの末尾に改行コードを挿入する。
(sedなどの動作により近くなる)
・-i
入力ファイルを処理結果で上書きする。
・-a
-p(-n)と併用することで、awkのようにセパレータによる行の分割を行った上で
文字列の操作を行える。
その他、多くのオプションが存在する。
#■sed的文字列操作
-eオプションを用いて、sedで文字列を置換する際に用いるsコマンドの構文を
ほぼそのままperlでも扱うことができる。
$ echo "I'm angry" | perl -ple 's/a/hu/g'
I'm hungry
スクリプト部分の内容は下記の通り。
s/[検索パターン]/[置換文字列]/[オプション]
置換演算子s///を用い、sed同様の順序でパターン・文字列を指定する。
末尾のオプション欄にgを置くことで、最初にマッチした文字列だけでなく
一致した文字列全てを置換できるのも同じ。
もちろん、検索は正規表現を利用できる。
$ echo -e "apple.jpg\nlemon.jpg\ngrape.png" | perl -ple 's/\.jpg$/.jpeg/g'
apple.jpeg
lemon.jpeg
grape.png
ex3では、行末を表す$を用いて.jpgで終わる行の拡張子部分を.jpegに変換している。
sed編で紹介した、マッチした文字列を置換後文字列で用いるということも
書き方は変わるが可能。
$ echo "パン" | perl -ple 's/パン/フライ$&/g'
フライパン
こちらでは"$&"を用いることでマッチした文字列を利用できる。
#■awk的文字列操作
-aオプションを用いれば、入力行文字列を指定したセパレータで区切った配列を扱うことができる。
$ echo "tea,coffee,water" | perl -aF, -nle 'print $F[1]'
coffee
-aオプションで入力行をセパレータで区切り、配列@Fに代入する。
(各要素は$F[i]で指定)
-Fオプションで、セパレータ文字を指定する(ex5ではカンマ)。
デフォルトではスペース。
ex5では、入力文字列"tea,coffee,water"に対し、
","で区切った際の2個目の要素(0始まりのため"$F[1]"で指定)を出力する
という処理を行っている。
awkの方がこの処理に特化している分使いやすいが、
perlの汎用性の高さをうまく組み合わせることで複雑な処理に応用できる。
echo -e "tea,coffee\napple,pan\nman,woman" | perl -aF, -nle 'if($F[1] eq "pan"){print}'
if文で$F[1](配列内第2要素)と"pan"を文字列一致判定(eq)し、
正の場合のみ該当行を出力(print)している。
もちろんほんの一例に過ぎないので、より複雑な処理を作成することが可能。
このように、sed,awkと比べperlは汎用性が高く、
perlのみでどちらもほぼ代用できる。
しかし、書き捨てで考えた際により文字列操作に特化した
sed,awkを用いた方がより簡便に書けるケースもあると思うので、
それぞれ覚えておいた上で選択ができるとよい。
#■参考
・各オプションについて参考
http://www.webhtm.net/perl/oneliner/oneliner_perloption.htm
http://qiita.com/ngyuki/items/d5dde70cf2de952cfb87
・置換演算子s///について参考
http://d.hatena.ne.jp/palmo/20060602/regexp9
http://www.kent-web.com/perl/chap7.html
・正規表現を用いた置換
http://www.atmarkit.co.jp/ait/articles/1610/18/news008.html