フィルタコマンド

以下に示すコマンドは、いずれも標準入力(または指定したファイル)から テキストデータを読み込み、決められた処理をしたあとその結果を 標準出力に書き出すフィルタコマンドである。これらをうまくパイプで 繋いで利用することで、複雑な処理を一瞬で完了させることができる。

以下の説明では、省略できるものを大括弧 [ ] で括って表記する。また、 記法説明で、[ファイル群] とあるものは、ファイルを指定すると そのファイルを処理対象とし、ファイル指定を省略すると標準入力を処理対象とする。

nkf - 漢字コードの変換

日本語を含むテキストを JIS / 日本語EUC / Shift-JIS コード のいずれかに変換する。変換する文字コードはオプションで指定する。

nkf -jJISコードに変換(デフォルト)
nkf -e日本語EUCコードに変換
nkf -sShift-JISコードに変換
nkf -w8UTF-8コードに変換
nkf -wUTF-8コード(BOM無)に変換

いくつか例を示す。

# ファイル foo をJISコードに変えたものを bar に保存
nkf -j foo > bar

# ファイル hoge をEUCコードに変換したものを happy プログラムに渡す
nkf -e hoge | ./happy
egrep - 検索パターンにマッチする行を抽出

指定したパターンにマッチする語を含む行を抽出して出力する。

egrep [オプション] パターン [ファイル群]

パターンには正規表現を利用する。

良く使うオプションには以下のものがある。

実行例:

# カレントディレクトリにあるファイル全てから hoge というパターンを
# 含む行を探して表示
egrep 'hoge' *

# カレントディレクトリにある全てのC言語ソースから printf を探す
egrep 'printf' *.c

# カレントディレクトリにある全てのC言語ソースから printf を探す
# ただし fprintf にはマッチしないように単語単位で探す
egrep -w 'printf' *.c

# カレントディレクトリより下にある全てのディレクトリにある
# C言語ソースから fgets というパターンを含むものを検索し、
# そのファイル名のみ表示
egrep -l 'fgets' **/*.c
(**/*.c はカレントディレクトリ以下全てにある *.c ファイル、
という意味でzshのみで利用できる)
wc - 行数・単語数・文字数の表示

入力の行数・単語数・文字数を数えて表示する。

wc [オプション] [ファイル群」

の書式で起動する。オプションは以下のとおり。

複数のオプションを組み合わせることもでき、wc -lc とすると、行数と文字数を表示する。
実行例:

# ~yuuji/zip_jp.txt から「山形県」を含むパターンを検索し、
# マッチした件数を数える
nkf -e ~yuuji/zip_jp.txt | egrep '山形県' | wc -l
sed - ストリームエディタ

入力を加工したものを出力する。多くの処理ができるが、 置換機能の使い方を覚えておけば十分だろう。

sed [オプション] 命令 [ファイル群]

良く使うオプションには以下のものがある。

「命令」の部分は多くのものが使えるが s 命令と p 命令 だけ覚えておこう。s命令は文字列の置換を行なう。

sed 's/置換前パターン/置換後文字列/'

とすると、入力行に「置換前パターン」に一致する部分があれば それを「置換後文字列」に置き換える。ただし、置き換えは1行につき 1回のみしか行なわれない。1行にあらわれる「置換パターン」を全て 置き換えて欲しいときは、

sed 's/置換前パターン/置換後文字列/g'

のように g フラグを追加する(globalのg)。
実行例:

# score.csv にあらわれる 太郎 を たろう に置き換えたものを出力
cat score.csv | sed 's/太郎/たろう/'

# CSV形式のファイルをタブ区切りに変換する
cat score.csv | sed 's/,/	/g'
(広い空白の部分はTAB文字で、コマンドラインでは C-v TAB で
 入力する)

p命令は、-n オプションと組み合わせて、 特定の行だけ出力したい場合に利用する。

sed -n '行位置指定p'

のようにして、入力データが「行位置指定」にマッチする行のみ 出力する。行位置指定には、/正規表現/ または 行番号 が書ける。行位置指定をカンマで区切って列挙すると 範囲指定になる。

# hoge.txt の中で Hello または hello にマッチする行のみ出力
cat hoge.txt | sed -n '/[Hh]ello/p'
# でもこれなら grep '[Hh]ello' hoge.txt とやればいいので普通使わない
# ↓sedのp命令は行番号で使うと便利

# ~yuuji/zip_jp.txt のうち、50行目のみを表示
cat ~yuuji/zip_jp.txt | sed -n 50p

# 本当に50行目というのがあってるか、cat -n で確認
cat -n ~yuuji/zip_jp.txt | sed -n 50p

# ~yuuji/zip_jp.txt のうち、10〜14行目のみを表示
cat ~yuuji/zip_jp.txt | sed -n 10,14p

# ~/Mail/inbox/1 のうち、先頭から空行までを表示する
cat ~/Mail/inbox/1 | sed -n '1,/^$/p'
(正規表現の先頭に来る ^ は行頭を意味し、
 正規表現の末尾に来る$は行末を意味する。
 よって /^$/という正規表現は、行頭のすぐ後ろに行末、つまり
 空行にマッチする)

awk - パターンマッチと処理を行なう専用言語

awkは、入力を「空白で区切られたフィールドの集まり」とみなして フィールドごとに分解した処理を簡単に書くことができる。

awk [オプション] awkプログラム文 [ファイル群]

「awkプログラム」は ' ' で括る。ここにはawk言語の全ての プログラムを書けるが、 print, printf だけ覚えておけば良い。 「awkプログラム」の部分では、入力行の各フィールドが $1, $2, $3,..., $NFで取り出せる。以下の例を見よ。

処理の元となるファイル sakata.txt

998	9980032 サカタシ	アイオイチョウ
998	9980828 サカタシ	アキホチョウ
998	9980862 サカタシ	アケボノチョウ
998	9980021 サカタシ	アサヒシンマチ
998	9980875 サカタシ	アズマチョウ
998	9980055 サカタシ	イイモリヤマ
998	9980018 サカタシ	イズミチョウ
99977	9997774 サカタシ	イタド
998	9980046 サカタシ	イチバンチョウ
998	9980836 サカタシ	イリフネチョウ

awkにこのデータを与えると、第1フィールドが $1、 第2フィールドが $2 のように自動的に変数に代入される。 この入力から、第2フィールドと第4フィールドだけを表示したいときは 以下のようにする。

cat sakata.txt | awk '{print $2, $4}'
9980032 アイオイチョウ
9980828 アキホチョウ
9980862 アケボノチョウ
9980021 アサヒシンマチ
9980875 アズマチョウ
9980055 イイモリヤマ
9980018 イズミチョウ
9997774 イタド
9980046 イチバンチョウ
9980836 イリフネチョウ

-F オプションを使うとフィールドの区切り文字を 変えることができる。

cat score.csv | awk -F, '{print $2, $4}'

とすると、区切り文字を , (カンマ)として フィールド分割を行なう。

sort - 入力レコードのソート
注意: panでは sort の代わりに gsort コマンドを 使う

1行1レコードとして入力行をソートした結果を出力する。 標準では行頭にあるフィールドを文字コード順にソートする。 sortで良く使うオプションは以下のとおり。

元となるデータ score.txt

山田太郎	50	70	20
公益太郎	90	80	70
飯森花子	91	79	72
鶴岡一人	60	60	40
酒田三吉	52	70	80
三川一二三	12	34	99

この構成は以下のようになっている。

第1フィールド氏名(文字列)
第2フィールド数学得点(数値)
第3フィールド英語得点(数値)
第4フィールド国語得点(数値)

sortコマンドによる並べ換えは以下のようになる。

# 漢字氏名でソート
cat score.txt | gsort

# 数学得点でソート
cat score.txt | gsort -n -k 2

# 英語得点でソート
cat score.txt | gsort -n -k 3

# 国語得点の高い順にソート
cat score.txt | gsort -nr -k 4

元となるデータがCSV形式だった場合はsortの -t オプションで区切り文字をカンマに変えれば良い。 score.csv

山田太郎,50,70,20
公益太郎,90,80,70
飯森花子,91,79,72
鶴岡一人,60,60,40
酒田三吉,52,70,80
三川一二三,12,34,99
# 数学得点でソート
cat score.csv | gsort -n -t , -k 2


# 国語得点の高い順にソート
cat score.csv | gsort -nr -t , -k 4

# 国語得点の高い順にソートしたものをTAB区切りに変換して出力
cat score.csv | gsort -nr -t , -k 4 | sed 's/,/	/g'
(sed命令にある広い空白の部分は C-v TAB とタイプして入力する)

# 数学得点の高い順にソートしたものを、氏名幅20桁にきれいに揃えて出力
cat score.csv | gsort -nr -t , -k 4 | \
	awk -F, '{printf "%-20s\t%d %d %d\n", $1, $2, $3, $4}'
uniq - 重複行の削除と重複数数え上げ

標準入力(または指定したファイル)で連続して同じ行が あった場合にそれを1行のみにする。有用な -c-u オプションは覚えておくとよい。

tr - 文字種変換

標準入力の中に登場する各文字を指定した文字にすべて変換する。 大文字を小文字にしたり,改行文字と空白を相互に変換するときに 用いる。

大文字から小文字へ

cat srcfile | tr '[A-Z]' '[a-z]' > destfile

空白を改行に全置換

cat srcfile | tr ' ' '\n' > destfile

-d オプションに続けて文字(または文字範囲) を指定すると,入力側からその文字を削除する。 次の例はMS-DOS改行(CR+LF)をUnix改行(LF)に 変換する。

cat dosfile | tr -d '\r' > unixfile
head - 先頭表示

標準入力(または指定したファイル)の先頭10行を出力する。 -数字 オプションで出力する行数を変えることができる。

# foo.txtの先頭10行を表示
head foo.txt

# カレントディレクトリにある *.c ファイル全ての
# 先頭を表示してlessで読む
head *.c | less
# less は、SPCで進んでbで戻る。qで終了

# ~yuuji/zip_jp.txt を町名でソートした先頭5行を表示
gsort -k 6 ~/zip_jp.txt | head -5
tail - 末尾表示

標準入力(または指定したファイル)の末尾10行を出力する。 headの逆。

tail コマンドは増えゆくファイルの末尾をつねに監視し続ける ときに利用する。これには -f オプションを指定する。

tail -f filename


本日の目次

目次