実用的なプログラムを作成する場合,すべてをゼロから自分で作るのではなく 典型的な処理は既存のプログラムを活用すると圧倒的に早く目的を達成できる 場合がある。
以下に示すコマンドは、いずれも標準入力(または指定したファイル)から テキストデータを読み込み、決められた処理をしたあとその結果を 標準出力に書き出すフィルタコマンドである。これらをうまくパイプで 繋いで利用することで、複雑な処理を一瞬で完了させることができる。
以下の説明では、省略できるものを大括弧 [ ] で括って表記する。また、
記法説明で、[ファイル群]
とあるものは、ファイルを指定すると
そのファイルを処理対象とし、ファイル指定を省略すると標準入力を処理対象とする。
日本語を含むテキストの文字コードを変換する。 変換する文字コードはオプションで指定する。主なオプションを示す。
-j | JISコードに変換(デフォルト) |
-e | 日本語EUCコードに変換 |
-s | Shift-JISコードに変換 |
-w8 | UTF-8コードに変換 |
-w | UTF-8コード(BOM無)に変換 |
--in-place |
変換対象ファイルを直接上書きして変換 |
-g |
ファイルの文字コードの自動判別結果を出力する |
いくつか例を示す。
# ファイル foo をJISコードに変えたものを bar に保存 nkf -j foo > bar # ファイル hoge をEUCコードに変換したものを happy プログラムに渡す nkf -e hoge | ./happy # ファイル bar をUTF-8コードに変換しそのまま上書きする nkf -w --in-place bar
指定したパターンにマッチする語を含む行を抽出して出力する。
egrep [オプション] パターン [ファイル群]
パターンには正規表現を利用する。ファイル群 を省略すると標準入力を読んでパターン検索する。
よく使うオプションには以下のものがある。
-i
アルファベットの大文字小文字を区別しない
-n
見付かった行の行番号を添えて出力する
-v
指定したパターンを含まない 行のみ出力する
-l
(小文字のエル)
パターンにマッチするファイルのファイル名のみ表示する
-w
指定したパターンを単語単位でマッチングさせる
(例: egrep 'month' files...
とした場合
month も
monthly もマッチするが、egrep -w 'month' files...
の場合は、monthly はマッチしない)
実行例:
# カレントディレクトリにあるファイルすべてから 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 [オプション] [ファイル群]
の書式で起動する。オプションは以下のとおり。
-l
行数を表示 (lines)
-w
単語数を表示 (words)
-c
文字を表示 (characters)
複数のオプションを組み合わせることもでき、wc -lc
とすると、行数と文字数を表示する。
実行例:
# ~yuuji/zip_jp.txt から「山形県」を含むパターンを検索し、
# マッチした件数を数える
nkf -e ~yuuji/zip_jp.txt | egrep '山形県' | wc -l
入力を加工したものを出力する。多くの処理ができるが、 置換機能の使い方を覚えておけば十分だろう。
sed [オプション] 命令 [ファイル群]
よく使うオプションには以下のものがある。
-e
次の引数を「命令」だと見なす-n
処理対象行をデフォルトで表示しない「命令」の部分は多くのものが使えるが 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言語の任意の
プログラムを書けるが、 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}'
とすると、区切り文字を ,
(カンマ)として
フィールド分割を行なう。単純なCSVファイルを処理するときは
awk -F,
によって特定のフィールドのみを対象とした
処理が簡単に書ける。
1行1レコードとして入力行をソートした結果を出力する。 標準では行頭にあるフィールドを文字コード順にソートする。 sortでよく使うオプションは以下のとおり。
-k N
ソートする基準(キー)となるフィールドを第N フィールドにする(Nは1から始まる整数)。デフォルト は第1フィールドで、フィールド番号は1から数え始める。
-t C
フィールドの区切り文字を C にする。
CSV形式であれば -t ,
と指定する。
-n
該当フィールドを数値だと見なしてソートする。
-r
逆順(降順)にソートする。
元となるデータ
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 | sort # 数学得点でソート cat score.txt | sort -n -k 2 # 英語得点でソート cat score.txt | sort -n -k 3 # 国語得点の高い順にソート cat score.txt | sort -nr -k 4
元となるデータがCSV形式だった場合はsortの -t
オプションで区切り文字をカンマに変えれば良い。
山田太郎,50,70,20 公益太郎,90,80,70 飯森花子,91,79,72 鶴岡一人,60,60,40 酒田三吉,52,70,80 三川一二三,12,34,99
# 数学得点でソート cat score.csv | sort -n -t , -k 2 # 国語得点の高い順にソート cat score.csv | sort -nr -t , -k 4 # 国語得点の高い順にソートしたものをTAB区切りに変換して出力 cat score.csv | sort -nr -t , -k 4 | sed 's/,/ /g' (sed命令にある広い空白の部分は C-v TAB とタイプして入力する) # 数学得点の高い順にソートしたものを、氏名幅20桁にきれいに揃えて出力 cat score.csv | sort -nr -t , -k 4 | \ awk -F, '{printf "%-20s\t%d %d %d\n", $1, $2, $3, $4}'
標準入力(または指定したファイル)で連続して同じ行が
あった場合にそれを1行のみにする。有用な -c
と -u
オプションは覚えておくとよい。
-c
1行にまとめるときに,行頭に何行をまとめたかを付加する。 たとえば,入力が
abc abc def def def hoge def
のときの uniq -c
の結果は,
2 abc 3 def 1 hoge 1 def
となる。頻度表を作るときに有用で,登場数を調べたい 1つの項目が1行になるようにしたファイルから,登場数ランキング を求めるときには,たとえば以下のようにする。
cat one-item-per-line.txt | sort | uniq -c | sort -nr
-u
連続する行でなくても既に登場した行と 同じものは出力しない。
標準入力の中に登場する各文字を指定した文字にすべて変換する。 大文字を小文字にしたり,改行文字と空白を相互に変換するときに 用いる。
大文字から小文字へ
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
2つ以上のファイルを指定し、各ファイルの同じ行を指定した順番で 横につなげたものを出力する。たとえば
file1.txt
秋の田のかりほの庵の苫をあらみ 春過ぎて夏来にけらし白妙の あしびきの山鳥の尾のしだり尾の
file2.txt
わが衣手は露にぬれつつ 衣干すてふ天の香具山 ながながし夜をひとりかも寝む
という2つのファイルがあったときに、paste コマンドを使用した例を示す。
paste file1.txt file2.txt
秋の田のかりほの庵の苫をあらみ わが衣手は露にぬれつつ
春過ぎて夏来にけらし白妙の 衣干すてふ天の香具山
あしびきの山鳥の尾のしだり尾の ながながし夜をひとりかも寝む
同じ行どうしが連結された結果となる。標準の区切りとしてTAB文字が 利用されるが、これを変えるには -d オプションを指定する。
paste -d, file1.txt file2.txt
秋の田のかりほの庵の苫をあらみ,わが衣手は露にぬれつつ
春過ぎて夏来にけらし白妙の,衣干すてふ天の香具山
あしびきの山鳥の尾のしだり尾の,ながながし夜をひとりかも寝む
-d オプションの後ろには区切りに利用する文字を指定する。 通常の文字以外に以下の指定ができる。
'\n' | 改行文字 |
---|---|
'\t' | タブ文字(デフォルト) |
'\\' | バックスラッシュ文字 |
'\0' | 空文字列(くっつける) |
-d ,:/ のように、複数文字を指定すると1つめの区切りが ,
2つめが : で、3つめが / で、さらにもしあれば , : / を順番に使う。
2つのCSVファイルを同じ行どうしで結合するには以下のようにする。
paste -d, file1.csv file2.csv > new.csv
標準入力(または指定したファイル)の先頭10行を出力する。 -数字 オプションで出力する行数を変えることができる。
# foo.txtの先頭10行を表示 head foo.txt # カレントディレクトリにある *.c ファイルすべての # 先頭を表示してlessで読む head *.c | less # less は、SPCで進んでbで戻る。qで終了 # score.csvを数学得点でソートした結果の先頭3行を表示 cat score.csv | sort -n -t, -k2 | head -3
標準入力(または指定したファイル)の末尾10行を出力する。 headの逆。
tail コマンドは増えゆくファイルの末尾をつねに監視し続ける
ときに利用する。これには -f
オプションを指定する。
tail -f filename
Webサーバやメイルサーバプログラムのログファイルを監視するときに 有用である。