パイプとは、コマンドの標準出力を次のコマンドに渡す処理のことをいいます。
パイプを使った処理のことを「パイプライン処理」といいます。
パイプライン処理は、縦線の記号「|」を使います。
記号「|」は、Shiftキーを押しながら、¥キーを押すと入力できます。
実際に使用してみます。
まず、catコマンドでtestfile1に、キーボードから入力した文字をリダイレクトさせます。
user@Dimension-2400C:~$ cat >>testfile1
abc
def
ghi
jkl
下の例では、catコマンドで、標準出力に書き出すところを、パイプを使ってsortコマンドに渡して、逆順(-r オプション)で表示しています。
user@Dimension-2400C:~$ cat testfile1 | sort -r
jkl
ghi
def
abc
上の例では、2つのコマンドを繋げていますが、3つでも、4つでも繋げることが出来ます。
フィルタとして動作するコマンド
フィルタとしての機能を持つコマンドとして
sort、head、tail、uniq、cut、grep、sed
を見ていきます。
sortコマンド(テキストをソート、マージ)
sortコマンドは、上記のようにファイルを行単位でソート(並べ替え)をできますが、次の例のように、ソート済みファイルとしてマージすることも出来ます。マージには、-mオプションを使います。
user@Dimension-2400C:~$ cat >testfile1
1
3
5
7
9
user@Dimension-2400C:~$ cat >testfile2
2
4
6
8
10
user@Dimension-2400C:~$ sort -nm testfile1 testfile2 >testfile3
user@Dimension-2400C:~$ cat testfile3
1
2
3
4
5
6
7
8
9
10
-nオプションは数字順に並べ替えです。
headコマンド(先頭行を表示する)
デフォルトでは先頭から10行表示します。
-n オプションで表示する行数を指定できます。
例 testfile3 の先頭3行だけを表示します。
user@Dimension-2400C:~$ cat testfile3
1
2
3
4
5
6
7
8
9
10
user@Dimension-2400C:~$ head -n 3 testfile3
1
2
3
tailコマンド(末尾を表示)
デフォルトでは末尾から10行を表示します。
-n オプションで表示する行数を指定できます。
例 testfile3 の末尾3行だけを表示します。
user@Dimension-2400C:~$ cat testfile3
1
2
3
4
5
6
7
8
9
10
user@Dimension-2400C:~$ tail -n 3 testfile3
8
9
10
uniq(ソート済みのファイルから重複した行を削除する)
使い方の例
user@Dimension-2400C:~$ cat >testfile3
1
3
5
7
9
2
4
6
8
10
3
5
7
9
user@Dimension-2400C:~$ cat testfile3 | sort -n | uniq
1
2
3
4
5
6
7
8
9
10
cutコマンド(各行から指定したフィールドを出力)
-c オプションで指定した位置の文字だけ表示できます。
(例)4から7文字を表示する場合
user@Dimension-2400C:~$ cat >testfile1
id 0001 agent_A
id 0002 agent_B
id 0003 agent_c
user@Dimension-2400C:~$ cut -c 4-7 testfile1
0001
0002
0003
-f オプションで指定したフィールドを表示できます。
-d オプションで、区切り文字を指定できます。デフォルトでは、タブになっています。
(例)スペース区切りの2番目~3番目のフィールドを表示
user@Dimension-2400C:~$ cat testfile1
id 0001 agent_A
id 0002 agent_B
id 0003 agent_c
user@Dimension-2400C:~$ cut -f 2-3 -d’ ‘ testfile1
0001 agent_A
0002 agent_B
0003 agent_c
grepコマンド(パターンにマッチする行を表示)
(例)カレントディレクトリでagentにマッチする行を表示
user@Dimension-2400C:~$ grep agent* *
grep: Desktop: ディレクトリです
grep: Documents: ディレクトリです
grep: Downloads: ディレクトリです
grep: Dropbox: ディレクトリです
grep: Music: ディレクトリです
grep: Pictures: ディレクトリです
grep: Public: ディレクトリです
grep: Templates: ディレクトリです
grep: Videos: ディレクトリです
grep: delorio_video: ディレクトリです
grep: test: ディレクトリです
grep: testatesaki: ディレクトリです
testfile1:id 0001 agent_A
testfile1:id 0002 agent_B
testfile1:id 0003 agent_c
上記処理の概要は、
$ grep agent* *で、カレントディレクトリのすべてのファイルに対してagent*にマッチする文字列を検索。
結果、ファイル名:マッチ行内容 という形で表示されています。
また、初心者の私のわからないことは、このgrepコマンドをカレントディレクトリで実行すると、どの階層まで探してくれるのかと言った疑問がわきます。
実際に、実験してみます。
user@Dimension-2400C:~$ cd test
user@Dimension-2400C:~/test$ tree
.
0 directories, 0 files
user@Dimension-2400C:~/test$ mkdir test
user@Dimension-2400C:~/test$ cd test
user@Dimension-2400C:~/test/test$ mkdir test
user@Dimension-2400C:~/test/test$ cd test
user@Dimension-2400C:~/test/test/test$ cat >magofile1
id 0001 type a name youko
id 0002 type b name kaori
id 0003 type c name hiroko
user@Dimension-2400C:~/test/test/test$ cp magofile1 magofile2
user@Dimension-2400C:~/test/test/test$ cp * ~/test/test
user@Dimension-2400C:~/test/test/test$ cp * ~/test
user@Dimension-2400C:~/test/test/test$ cd ~/test
user@Dimension-2400C:~/test$ tree
.├── magofile1
├── magofile2
├── siftjis.txt
└── test
├── kofile1
├── kofile2
└── test
├── magofile1
└── magofile2
2 directories, 6 files
user@Dimension-2400C:~/test$ grep name* *
magofile1:id 0001 type a name youko
magofile1:id 0002 type b name kaori
magofile1:id 0003 type c name hiroko
magofile2:id 0001 type a name youko
magofile2:id 0002 type b name kaori
magofile2:id 0003 type c name hiroko
grep: test: ディレクトリです
user@Dimension-2400C:~/test$
以上のように、カレントディレクトリ直下のファイルをマッチングしてくれます。
以下の例のように、-Rオプションをつけると配下のすべてのディレクトリ内を再帰的にマッチングしてくれます。
user@Dimension-2400C:~/test$ grep -R name* *
magofile1:id 0001 type a name youko
magofile1:id 0002 type b name kaori
magofile1:id 0003 type c name hiroko
magofile2:id 0001 type a name youko
magofile2:id 0002 type b name kaori
magofile2:id 0003 type c name hiroko
test/magofile2:id 0001 type a name youko
test/magofile2:id 0002 type b name kaori
test/magofile2:id 0003 type c name hiroko
test/magofile1:id 0001 type a name youko
test/magofile1:id 0002 type b name kaori
test/magofile1:id 0003 type c name hiroko
test/test/magofile2:id 0001 type a name youko
test/test/magofile2:id 0002 type b name kaori
test/test/magofile2:id 0003 type c name hiroko
test/test/magofile1:id 0001 type a name youko
test/test/magofile1:id 0002 type b name kaori
test/test/magofile1:id 0003 type c name hiroko
この-Rオプションですが他にも、lsコマンドなどでも再帰的動作をしてくれます。
どのコマンドが再帰的に動作してくれるかは、man コマンド名で検索し、文中にrecursiveという表現があるかどうかで判断出来ます。
それにしても、疑問なのは、ノーオプションで*(ワイルドカード)を使った時に、カレントディレクトリ直下まで動作するコマンドと子ディレクトリまで動作するコマンドがありどこで区別できるのかと言ったことです。例えば、findコマンドの場合、配下のすべてのディレクトリまで再帰的に検索マッチングしてくれます。今それについて調査中です。
sed(文字列の置換,行の削除を行う)
文字列の置換の例
user@Dimension-2400C:~$ cat testfile1
id 0001 agent_A
id 0002 agent_B
id 0003 agent_c
user@Dimension-2400C:~$ sed -e “s/agent_/はらほれ ふん/g” testfile1
id 0001 はらほれ ふんA
id 0002 はらほれ ふんB
id 0003 はらほれ ふんc
注意すべきなのは
$ sed -e “s/agent_/はらほれ ふん/g” *
で「agent」を「はらほれ ふん」に変換していますが、ストリーム上で変換されているだけで、それをファイルに書き出さないと保存されないという事です。
行の削除の例
user@Dimension-2400C:~$ cat testfile1
id 0001 agent_A
id 0002 agent_B
id 0003 agent_c
user@Dimension-2400C:~$ sed -e “1,2d” testfile1
id 0003 agent_c
上の例ではtestfile1の1行目から2行目が削除されています。
これも、あくまでストリーム上のことで入力ファイルは変更されていないことに注意しましょう。