Ansatzの備忘録

勉強したことあるいはふと思い立ったこと

シェルワンライナー160本ノック問題17

問題17 コマンドが使えないときのコピー

トラブルで cat や cp などの外部コマンドが一切使えなくなった状況で、 Bash のビルトインコマンドや機能だけで /etc/passwd を ~/a にコピーする問題だった。まったく思いつかなかった。

正解例は

while read ln ; do echo $ln ; done < /etc/passwd > ~/a

である。ファイル passwd から一行ずつ読み込んで echo で出力するという方法だった。ただこの方法だと行頭に空白がある場合に対応できないらしい。ちょっと実験してみることにする。

echo ' hoge' > test

で行頭に空白を入れたテキストファイルを作る。そして正解例のコマンドを実行する:

while read ln ; do echo $ln ; done < test > ~/testread

そうして testread を cat で出力させると確かに行頭の空白が消えていた。これは read の仕様な気がするので man で確かめてみる。

標準入力、 または -u オプションの引き数として指定されたファイル・ディスクリプター fd から 1  行を読み込み、最初の単語を最初の  name に代入し、2 番目の単語を 2 番目の name に代入します。以降も同様です。 余った単語とそれらの間の区切り文字は、最後の name に代入されます。 name  よりも標準入力から読み込んだ単語の方が少ない場合には、  余っている name には空文字列が値として代入されます。 IFS 中の文字が、行を単語に分割するために使われます。

おそらく空白が区切り文字と認識されてしまい、出力されないのだと思う。行頭の空白をちゃんと出力するには

echo "$(</etc/passwd)" > ~/a

とすればいい。区切り文字を認識する処理がないので空白がちゃんと出力される。