yn2011's blog

技術メモ

peeコマンドについて混乱したので調べた(シェルスクリプト)

環境

混乱

$ matsuya | pee cat "grep -o ." rev
んどうーレカニミ
ミニカレーうどん
ミ
ニ
カ
レ
ー
う
ど
ん
  • シェルスクリプトってpee cat "grep -o ." revみたいにコマンドを並べられるんだっけ?
  • そもそもpeeを初めて見た。peeとは?

pee

  • teeの出力先がパイプになったコマンド。パイプだからt→pなのかも。
SYNOPSIS
       pee [--[no-]ignore-sigpipe] [--[no-]ignore-write-errors] [["command"...]]
  • teeはこんな感じで引数に複数のファイルを指定できる。
$ echo foo | tee bar.txt baz.txt
$ cat bar.txt
foo
$ cat baz.txt
foo
  • つまりpeeも引数として複数のコマンドを指定できる...?
$ echo foo | pee cat cat cat
foo
foo
foo
  • おお、やはり。
  • ということで最初のワンライナーを見返してみる。これはpeeの引数のコマンドに共通の標準入力を与えているものなのか。
$ matsuya | pee cat "grep -o ." rev

オプション付きコマンドの場合

  • "grep -o ."のダブルクォートはもしかするとコマンドにオプションを付けるときに必要なのかも...?
  • 試しに下記を実行してみる
$ echo foo | pee cat cat "cat -n"
foo
foo
     1  foo
  • 最後のcatだけ行番号付きで出力された。
  • やっぱりコマンドにオプションを指定するときはダブルクォートで囲ってあげる必要があるということみたい。
  • 考えてみれば、シェルスクリプトでは半角スペースが引数の区切りとして解釈されてしまうし仕方ない。

出力順

  • peeの引数に指定されたコマンドは先頭から順に終了するとは限らない。
  • 実際、最初に示した例ではrevcat"grep -o ."の順に標準出力に書き込まれている。
  • 何度か試すと時々順序が入れ替わる様子が観察できたので固定の出力が得られることは期待できないみたい。
  • peeを親とした子プロセスがforkされて個々のコマンドが並行(コンカレント)に実行されているから...だと思う (違っていたらすまん)