bashで標準入力すべてを得るTIPS

bashで標準入力すべてを得るには

read -rd '' s; echo "$s"

注意しなきゃいけないのはechoで出力する時に「"」をつけ忘れないこと!

つけているときちんと出力するが

$ echo -e "ab\ncde\ndef" | (read -rd '' s; echo "$s")
ab
cde
def

つけ忘れるとechoが改行コードをフィールドセパレータとして解釈してしまう。

$ echo -e "ab\ncde\ndef" | (read -rd '' s; echo $s)
ab cde def

標準入力からデータを受け取ってそれをCソースとしてコンパイルし実行するfunctionを定義してみた。

$ function foo(){ d=/tmp/$$_;read -rd '' s; echo "$s">$d.c; gcc $d.c -o $d.out; $d.out; rm $d.{c,out}; } ; echo -e '#include <stdio.h>\nmain(){\nprintf("hello,world\\n");\n}'|foo
hello,world

うまくいった。

サブシェルで書くと

$ echo -e '#include <stdio.h>\nmain(){\nprintf("hello,world\\n");\n}' |  (d=/tmp/$$_;read -rd '' s; echo "$s">$d.c; gcc $d.c -o $d.out; $d.out; rm $d.{c,out}; )
hello,world

サブシェルすげぇ。rubyイテレータ(いまはブロック)みたいだ。
実はbashってすごいんじゃないかと思いはじめた今日この頃。

$ echo -e "ab\ncde\ndef" | (read -rd '' s; echo "$s") | cat -n
     1	ab
     2	cde
     3	def

read文の直後にパイプをつなげられたらほんとにかっこいいんだけどな…ってそりゃrubyか。
まあ、「read -rd '' s; echo "$s"」このフレーズがrubyのSTDIN.readと同じ機能を持つって覚えればOK

ほかにもevalとかにも応用可能

$ echo -e 'for i in {1..5}\ndo\necho $i\ndone' | ( read -rd '' s; echo "$s";eval "$s" )
for i in {1..5}
do
echo $i
done
1
2
3
4
5

すげえteeいらず。変数最高!(嘘

他言語の例

ちなみに標準入力から得たすべてを変数に入れるにはperlなら

$ echo -e 'a\nbc\ndef\ng'| perl -e 'print <STDIN>;'
a
bc
def
g

rubyなら

$ echo -e 'a\nbc\ndef\ng'| ruby -e 'print STDIN.read'
a
bc
def
g