社内の勉強会で シェルの勉強という題目でsedとawkを学んだので、備忘録。
sed
受け取った入力をフィルタリングして返す。特に置換・マッチングが得意。
Vimの文字列置換方法は知ってたけど、ツールとしてのsedは同じような記法でいける。
基本的な使い方
$ echo "ponzponz" | sed 's/z/ZZ/' ponZZponz
sed 's/(置換元の文字)/(置換後の文字)/'
の書き方をすればOK。
ただ、この書き方だとヒットした最初の文字だけ置換する。ヒットした全ての文字を置換したいときは、最後の/の後にgをつければOK。
$ echo "ponzponz" | sed 's/z/ZZ/g' ponZZponZZ #後ろの文字も置換された!
上の例だと全てecho
で返された文字列を置換したけど、実際に使う場面だとファイルの中身に対して行うことが多いでしょうね。
この場合は置換の命令の後ろにファイル名を書いてあげる。
ちなみにこのやり方だと元ファイルが上書きされることはないです。
$ cat riders.txt Kuuga, 2000/01/30, 49 Blade, 2001/01/28, 51 Ryuki, 2002/02/03, 50 555, 2003/01/26, 50 $ sed 's/Blade/Agito' riders.txt Kuuga, 2000/01/30, 49 Agito, 2001/01/28, 51 <- マッチしたものだけ置換されている Ryuki, 2002/02/03, 50 555, 2003/01/26, 50
複数条件を一気にマッチングさせたい場合は -e
オプションをつければいいらしいが、横に長くなってめんどいので条件をファイルに外だし可能。
# 全てディケイドにする置換条件 $ cat onore_dicade s/Kuuga/Dicade/ s/Blade/Dicade/ s/Ryuki/Dicade/ s/555/Dicade/ # 全てディケイドに $ sed -f onore_dicade riders.txt Dicade, 2000/01/30, 49 Dicade, 2001/01/28, 51 Dicade, 2002/02/03, 50 Dicade, 2003/01/26, 50
awk
sedと同じテキスト処理ができる。構造を持ったテキスト(CSV, TSVとか)ならばsedよりもawkで処理した方が楽。
基本的な使い方
$ awk '/Ryuki/ { print $1 }' riders.txt Ryuki, 2002/02/03, 50
awk '(マッチング条件) (アクション)' (インプットファイル名)
と書けばOK。
デフォルトで空白区切りで行を認識して、$n でn番目の要素を取得できる。もし区切り文字を変更したい場合は -F
オプションをつけてあげる。
# 1月始まりのライダー番組を話数と一緒に出す $ awk -F ',' '/01/ { print $1, "全(", $3, ")話"}' riders.txt Kuuga 全( 49 )話 Blade 全( 51 )話 555 全( 50 )話
使い所
今の所、簡単な置換はsed
、ガリガリパターンマッチングしてテキスト編集するならawk
使う。
ログファイル解析や、バッチ・Excelで処理する時の下準備に使えそう。
勉強会で話してたときは、パイプでsort
やuniq
で並び替えやら重複削除すれば傾向の把握できるねーと盛り上がってた。
ただ、数百万行になるファイルを扱う場合は、head
で数行で試してからsed/awkでテキスト処理かけた方が効率良さそう。。。
個人的には、Javaとかでバッチ処理する時の前処理に使いたい。
仕事でJavaバッチ使った時に、
数百万行のCSVから全てのテキスト読み込み→編集・ソート・重複削除とか処理→出力or別のバッチに渡す...
こんなことやってパフォーマンスが御陀仏になったことがあったから、
下準備としてsed/awk
で必要な情報をある程度絞ってからJavaバッチに渡すといったことができるとJava側もシンプルに処理できなと思った次第。
備忘録ここまで。