awk は基本的に1行ずつ処理をするのだけども、XMLを見るときなんかはどうしても複数行処理したくなることがある。
そんなときに便利な関数が「getline」だ。
getline を引数なしで呼び出すと、今処理している行の次の1行読み込んで、$0とかNFとかに新しい値をセットする。
(前の$0とか消えてしまうけども、それが嫌ならgetlineに引数を渡すと、そこに格納してくれるようだ)
実際に試してみた方が早いと思うので、以下のようなXMLファイルから、特定の値をとりだすことをやってみる。
[root@localhost ~]# cat example.xml
<?xml version="1.0">
<gloup name="gloup1">
<menber>member1</menber>
<menber>member2</menber>
<menber>member3</menber>
</gloup>
<gloup name="gloup2">
<menber>memberA</menber>
<menber>memberB</menber>
<menber>memberC</menber>
</gloup>
<gloup name="gloup3">
<menber>memberX</menber>
<menber>memberY</menber>
<menber>memberB</menber>
</gloup>
[root@localhost ~]#
gloup1 と gloup3のmemberだけ取り出したい、というときに、getlineを使うと比較的簡単に処理が出来る。
awk '$1 == "<gloup" && $2 ~ /gloup(1|3)/ { print $2 ; while ( getline ) { if ($0 ~ /<\/gloup>/ ) { break } else { print $0 } } }' example.xml
while とか if は一般的なプログラム言語とだいたい同じ動きをする。
ここでは、gloup要素を発見すると、2カラム目を参照し、それがgloup1かgloup3だった時に、</gloup>が来るまで行を出力している。
実行結果はこんな感じ。
[root@localhost ~]# cat example.xml
<?xml version="1.0">
<gloup name="gloup1">
<menber>member1</menber>
<menber>member2</menber>
<menber>member3</menber>
</gloup>
<gloup name="gloup2">
<menber>memberA</menber>
<menber>memberB</menber>
<menber>memberC</menber>
</gloup>
<gloup name="gloup3">
<menber>memberX</menber>
<menber>memberY</menber>
<menber>memberB</menber>
</gloup>
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# awk '$1 == "<gloup" && $2 ~ /gloup(1|3)/ { print $2 ; while ( getline ) { if ($0 ~ /<\/gloup>/ ) { break } else { print $0 }
} }' example.xml
name="gloup1">
<menber>member1</menber>
<menber>member2</menber>
<menber>member3</menber>
name="gloup3">
<menber>memberX</menber>
<menber>memberY</menber>
<menber>memberB</menber>
[root@localhost ~]#
複数の機器でミドルウェアのセットアップとかした時、いちいち結果をGUIで確認すると時間がかかって仕方がない。
直接XMLを見るときに、こんな感じで該当箇所だけ抜き出せると良い感じ。
(sub 関数とか上手く使えば出力結果を綺麗に整形できると思うけども、今回は割愛)
コメントをお書きください