/Linuxコマンド

テキスト処理

sed と awk

ストリームを行単位で置換・削除する sed と、列を扱う小さな言語 awk。よく使う形に絞って紹介。

sed行を置換・削除する

ファイルやテキストの文字列を置き換えたり、特定の行を消したりします。複数のファイルをまとめて書き換えるのにも使います。

bash
sed [オプション] '<スクリプト>' [ファイル...]
オプション意味
-iファイルを直接書き換える(-i.bak で元をバックアップ)
-n自動で出力しない(p で出したい行だけ出す)
-E拡張正規表現を使う(+ ? () | がそのまま使える)
-eスクリプトを複数指定する

置換

bash
$ sed 's/foo/bar/' file.txt          # 各行の最初の foo を bar に
$ sed 's/foo/bar/g' file.txt         # すべての foo を bar に
$ sed -i 's/http:/https:/g' *.html   # ファイルを直接書き換える
$ sed -i.bak 's/DEBUG=1/DEBUG=0/' .env
$ sed 's#/usr/local#/opt#g' paths.txt  # 区切りは / 以外でもよい
$ sed -E 's/([0-9]+)-([0-9]+)/\2-\1/' dates.txt   # グループを入れ替える

行を選ぶ・消す

bash
$ sed -n '10,20p' file.txt           # 10〜20行目だけ表示
$ sed -n '/START/,/END/p' log.txt    # START から END までの範囲
$ sed '/^#/d' config.conf            # # で始まる行(コメント)を消す
$ sed '/^\s*$/d' file.txt            # 空行を消す
$ sed '1d' data.csv                  # 1行目を消す
$ sed -i '$a\最後に追加する行' file.txt
$ sed -i '1i\先頭に入れる行' file.txt

awk列を扱う

awk は、入力を1行ずつ読み、空白で区切った列を $1 $2 … として扱います。$0 は行全体、NF は列の数、NR は行番号です。

bash
awk '条件 { 処理 }' [ファイル...]
bash
$ ps aux | awk '{print $2, $11}'          # 2列目(PID)と11列目(コマンド)
$ awk -F: '{print $1}' /etc/passwd        # : 区切りの1列目
$ awk -F, 'NR > 1 {print $3}' data.csv    # 見出し行を飛ばして3列目
$ awk '$3 > 100' data.txt                 # 3列目が100より大きい行
$ awk '/ERROR/ {n++} END {print n}' app.log            # ERROR の行数
$ awk '{sum += $5} END {print sum}' access.log         # 5列目の合計
$ awk '{print $NF}' file.txt              # 各行の最後の列
$ awk '!seen[$0]++' list.txt              # 順番を保ったまま重複を除く
$ df -h | awk 'NR==1 || $5+0 > 80'        # 使用率80%超えのディスク(見出しも)
変数意味
$0行全体
$1 $2 …1列目・2列目…
NF / $NF列の数 / 最後の列
NR何行目か
FS / -F入力の区切り文字
OFS出力の区切り文字(-v OFS=, で指定)
bash
$ awk -F, -v OFS='\t' '{print $2, $1}' data.csv    # CSV の列を入れ替えてタブ区切りに
$ awk '{printf "%-20s %5d\n", $1, $2}' stats.txt   # 幅を揃えて表示