LoginSignup
160
131

More than 5 years have passed since last update.

コマンドとコマンドをつなぐ糊

Last updated at Posted at 2015-12-17

環境

Terminal
$ bash --version
GNU bash, version 4.3.30(1)-release (x86_64-apple-darwin14.0.0)

パイプ (pipe) commandA | commandB

正式にはPipeline。|&でも動く(2019/03/16補足: |& では標準出力と標準エラー出力を次のプロセスの標準入力につなぎます)。
$ man bash より

Pipelines
A pipeline is a sequence of one or more commands separated by one of the control
operators | or |&.

Terminal
$ seq 1 5 | grep 1
1

$ seq 1 5 |& grep 1
1

[パイプ + α] 標準入力自体を解釈して実行 commandA 'commandB' | bash

Terminal
$ echo yes | bash
y
y
y
y
...

# yesコマンドが実行される
Terminal
$ yes 'echo $RANDOM' | bash
212
16621
7312
2233
19266
2762
Terminal
$ echo $$; echo 'echo $$' | bash
88208
88278

# プロセスのIDは違う

$ man bash より

DESCRIPTION
Bash is an sh-compatible command language interpreter that executes commands read
from the standard input or from a file.

単に「標準入力かファイルを解釈して実行するよ」とあるだけで、特にこのテク自体には名前はないのかも。

[パイプ + α] xargs commandA | xargs -I@ commandB @

標準入力を次のコマンドの引数にする。ただのxargsの応用例。よく使う慣用句。

Terminal
$ echo "-al" | xargs -I@ ls @
drwxr-xr-x+ 133 greymd           greymd     4522 Dec 17 13:34 .
drwxr-xr-x    7 root             greym       238 Oct 25  2014 ..

# ls -al が実行される

コマンド置換 (command substitution) commandA $(commandB)

commandA `commandB` とも書ける。
commandの実行結果が文字列として認識される。

Terminal
$ ls $(echo '-al')
drwxr-xr-x+ 133 greymd           greymd     4522 Dec 17 13:34 .
drwxr-xr-x    7 root             greym       238 Oct 25  2014 ..

# ls -al が実行される
Terminal
$ `echo "yes"`
y
y
y
y
y

# yesが実行される

$()は入れ子にできる`(backtick)は入れ子にできない。
$()はcshとかtcshじゃ動かない。

Terminal
$ cat $(echo $(echo "/etc/passwd"))

プロセス置換 (process substitution)

このページが良くまとまってた。

出力対象のプロセス置換 commandA >(commandB)

Terminal
$ seq 10 | tee >(grep -v 1 > output)
1
2
3
4
5
6
7
8
9
10

$ cat output
2
3
4
5
6
7
8
9

commandA | tee >(commandB) | commandC という形式で使うと、commandAの出力をcommandBcommandCの両方で扱え、かつ両方とも標準出力に出せる。一旦パイプが枝分かれになって、出口で合流した感じ。

Terminal
$ seq 10 | tee >(grep 1) | grep 2
1   # grep 1 による出力
10  # grep 1 による出力
2   # grep 2 による出力

入力対象としてのプロセス置換 commandA <(commandB)

これはよく使う。<(command)commandの実行結果が記載されたファイルのように振る舞う。

Terminal
$ cat <(seq 10)
1
2
3
4
5
6
7
8
9
10

# これと挙動としては同じ
$ seq 10 > tmp
$ cat tmp
1
2
3
4
5
6
7
8
9
10

ファイルのように振る舞うんでしょ?ファイル名は?→ファイルディスクリプタでした。

Terminal
$ echo <(seq 10)
/dev/fd/63

複合コマンド(Compound Commands) (commandA; commandB;) {commandA; commandB;}

複数のコマンドをコロンで区切って、出力を合体させる。
()はサブシェル (subshell)、{}は何と表現すればよいのか。

Terminal
$ (echo '123'; echo '456')
123
456

{}はサブシェルではなく、現在のプロセスで実施されるとのこと。確かにサブシェルだけプロセスIDが違う。

Terminal
$ echo $BASHPID; (echo $BASHPID;); { echo $BASHPID; }
75461
76279
75461
160
131
1

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
160
131