仕事でシェルスクリプト書くことが、たまにあるのですが参考になるコードをウェブで物色していたところ、以下のようなコードを見かけました。
1 | jq <<< '{}' |
不等号3つのパターンを初めてみたので、何だこれ?という感じになりまして、この機会に調べてみることにしました。
マニュアル
Bashのマニュアルにバシッと記載がありました。
Bash Reference Manual - 3.6 Redirections
不等号3つのパターンは、3.6.7 Here Strings
というんですね。知らなかった。
サンプル
せっかくなので、リダイレクションの全パターンについて、サンプルコードと結果を載せておきます。
サンプルで使うhoge.txt
の中身は文字列hoge
です。
3.6.1 Redirecting Input
1 | $ sed -e 's/hoge/fuga/g' < hoge.txt |
説明不要でしょうけど、mysqlとかでクエリ実行するときによく使いますね。
3.6.2 Redirecting Output
1 | $ echo 'hoge' > hoge.txt |
リダイレクションの動作を制御するためのnoclobber option
というものがあって、set -C
で有効化できるようです。そうすると、ファイルが存在した場合に上書きが出来なくなります。知らんかったぞ!
1 | $ set -C; echo 'hoge' > hoge.txt |
noclobber option
設定時でも、上書きしたい場合は>|
でリダイレクトすると強制上書き可能。
1 | $ echo 'hoge' >| hoge.txt |
これはいつか使えそうな気がする…。
3.6.3 Appending Redirecting Output
1 | $ echo 'hoge' >> hoge.txt |
これは追記するときの常套手段ですね。
3.6.4 Redirecting Standard Output and Standard Error
1 | $ curl -sS hoge &> hoge.txt |
マニュアルには>&
も同じだが、&>
が好ましいと書いてある。互換性の問題のようですが。
なお、意味的には&>
と2>&1
は同じとのこと。これからは&>
を使おうかな、短くて覚えやすい。
また>&
は数字や、ハイフンを出力してはいけないとのこと、それをすると意図しないファイルディスクリプタに出力してしまうと。
ここの理解はずっと若干曖昧なままになっているので、今度独立して調べよう。
3.6.5 Appending Standard Output and Standard Error
3.6.4の追記版ですね。
1 | $ curl -sS hoge &>> hoge.txt |
別の書き方としては
1 | $ curl -sS hoge >> hoge.txt 2>&1 |
3.6.6 Here Documents
シェルスクリプトでHere Documents使ったことなかった…
1 | #!/bin/bash |
DELI
はデリミター文字列なので、何でも良し。ポイントとしては文字列になるのではなく標準入力であるということです。上の例ではcat
コマンドの実行結果として変数STR
に代入しています。
3.6.7 Here Strings
ようやく本題ですが、不等号3つを重ねたものはHere Strings
です。Here Documents
の一行版と思えば良さそうです。こちらも標準入力として不等号左側のコマンドに対して与えられます。
1 | $cat <<< hoge |
公式マニュアルを見ると、[n]<<< word
という記述方法になっています。このn
はファイルディスクリプタを表していて、デフォルトは標準入力ですが、任意のファイルディスクリプタに変更可能です。※ちなみに他のリダイレクションも同様にファイルディスクリプタを指定できるものはマニュアルに[n]
の指定があります。
3.6.8 Duplicating File Descriptors
マニュアルの記載だと [n]<&word
または [n]>&word
と書いてある。cronの設定とかで標準エラー出力2
を標準出力1
にするのは、この構文を使っているんですね。Duplicating
だから複製ということなのか、じゃあエラー出力自体は残るようなイメージになるけど、実際には2が1に合成されているので、名称と動作が直感的ではないのだろうか…
3.6.9 Moving File Descriptors
知らなかったし、使ったこともなかった。
[n]<&digit-
または [n]>&digit-
となっている。
むしろ意味的には、2<&1-
の方がしっくりくる気がする。実際に試してみると、想像どおりの動きをしてくれる。
1 | $ curl -sS hoge > /tmp/test 2>&1- |
3.6.8との違いは何なのだろうか…。これも今後の研究の余地がある。
3.6.10 Opening File Descriptors for Reading and Writing
[n]<>word
まったく意味不明、何に使うのだろう。
ネットで見つけたサンプルコードを参考にして下記のようなスクリプトを書く。
1 | #!/bin/bash |
実行するとこうなる。
1 | $ sh hoge.sh |
シェルスクリプトで標準入出力以外を使ったことがなかったので知らなかっただけで、そりゃ使えるよねぇという話でした。
まとめ
Bashのマニュアル面白い!発見が多い、というかもっと早く読んどけよという話ですが。