LoginSignup
5
3

More than 1 year has passed since last update.

[Linux]sedコマンドとawkコマンドについて

Posted at

はじめに

sedコマンドとawkコマンドについて学んだのでまとめてみました

sedコマンド

sedとは「Stream Editor」から来ています。そう、エディタのことです。ただし、sedコマンドでは非対話的エディタのため、編集し出力をしても元のファイルに変更は加えないという特徴があります。

terminal
% sed オプション <スクリプト> <対象ファイル>

おそらくこれだけではわからないと思います。使用例としては以下です。

terminal
% sed 1,5d sample.txt

% sed 's/aaa/bbb/g' sample.txt

うん、もっとわからなくなったはずです笑
とりあえず、sedコマンドは多くのことができるコマンドですが主なコマンド(d:削除、p:行を表示、s:行の置換)を紹介していきます。

行の削除

sedコマンドでは、アドレスで指定した行のみ作用(削除)します。

例えば、以下のようなファイルがあったとします。

sample.txt
Beer
BeerBeer
BeerBeerBeer
Beeeeeeeeeeeeeeer!

それでは行を削除してみます。

terminal
% sed 1d sample.txt
BeerBeer
BeerBeerBeer
Beeeeeeeeeeeeeeer!

1行目のBeerが削除されていることがわかります。
行は範囲指定できます。

terminal
% sed 1,3d sample.txt
Beeeeeeeeeeeeeeer!

ちなみにアドレスを指定せずにコマンドを打てば全削除になりますし、アドレスに$を使用すると最終行までを意味することができます。$を使うときは、シェルに解釈させないために''で囲みましょう!

terminal
% sed d sample

% sed '3,$d' sample.txt
Beer
BeerBeer

上記では行番号で削除するものを決めていましたが、正規表現でもOKです。
以下の場合は、先頭がBから始まる行を指定しています。

terminal
% sed /^B/d sample.txt

行を表示する

今回はシンプルで削除した際にdとしていたところをpとするだけです。

terminal
% sed 1p samole.txt
Beer
Beer
BeerBeer
BeerBeer
BeerBeerBeer
BeerBeerBeer
Beeeeeeeeeeeeeeer!
Beeeeeeeeeeeeeeer!

あれ、、、2重になっている、、、
これはできれば各自調べて欲しいのですが、、「パターンスペース」の出力も同時に行われているためです。

これではみづらいので、-nオプションを使えばパターンスペースの出力をなくすことができます!

terminal
% sed -n 1p sample.txt
Beer

行の置換

置換ではsコマンドを使用します

terminal
% sed 's/置換する文字列/置換後の文字列/フラグ' ファイル名

フラグは省略可能です。
ただし、省略した場合は、見つかった文字列の最初しか置換しないので、フラグのところにgとつけてあげます。すると、見つかった文字列は全て置換します。

なお、置換が発生したときのみ出力するpフラグを使うと便利です

terminal
% sed 's/beer/wine/gp' sample.txt

ちなみに、拡張表現を使ってグループ化、参照をうまく使えば、以下のようにすることも可能
()でグループ化したものは\1や\2といった形で参照できます。

sample.txt
My wine
My beer
terminal
% sed 's/My \(.*\)/--\1--/' sample.txt
--wine--
--beer--

awkコマンド

awkコマンドはsedよりも高性能にテキストの抽出や加工をします。
書き方は以下のとおりです。

terminal
% awk パターン {アクション} ファイル名

当然これだけではわかるまい!と言うわけで解説。
awkではパターンにマッチした場合のみアクションを行います。もちろん、パターンは省略可能でその場合は、全データが対象になります。

具体例を見ていきます。例えば、以下の場合であれば第1フィールドがsで始まるレコードを行番号付きで表示します。

terminal
% awk '$1 ~ /^s/ {print NR,$0}' test.txt 

$1,,,,,$9は、レコードの並びを分割した際の各フィールドを示し、$0はレコード丸々を示します。また$NSはいわゆる最後のフィールドを指し、$(NS-1)とすることも可能です。

パターンの指定方法としては以下です。

terminal
% awk `$9 ~ /^cp/` {print $5,$8}

この場合は、第9フィールドの先頭がcpで始まっているレコードに対して、第5、8フィールドを表示させるコマンドになります。

より実践的な例としては、csvファイルで平均を考えるときは以下のようにする。

terminal
% aws -F, `{sum+= $NF} END {print "Average:",sum/NR}` score.csv

ここで-F,はフィールド区切りの文字を指定するためのオプションであり、ENDはそれよりも前のアクションが終わってから次のアクションをさせるものです。
つまり、フィールド区切りのレコードに対して、最後のフィールドの合計値を求めた後に、平均を表示してます。ちなみに、NRはこれまで読み込んだレコード数が代入された組み込み変数です。

おわりに

以上、sedとawkについてまとめました。
便利なコマンド?だと思われるので、是非使い慣れたいものです!

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3