インデントされたファイルを “while read” コマンドでループさせるとインデントが消えてしまう問題に対処
はじめに
シェルスクリプトで、インデントされたテキストファイルを while read
構文で読み込み処理したいが、インデントされている行の行頭のスペースが消えてしまうのでなんとかしたいという質問がありました。
検証環境
$ uname -moi
x86_64 x86_64 GNU/Linux
$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
問題
以下のようなファイルがあります。2行目がスペースでインデントされています。
$ cat a.txt
111
222
333 444
これを while read
構文で読み込みループさせたいが、2行目の行頭のスペースが消えてしまうということでした。
$ while read -r line; do
echo "$line"
done <a.txt
111
222
333 444
解決方法は IFS
環境変数のクリア
解決方法は非常に単純で、 IFS
環境変数をクリア(空)にしてやることで対処できます。
$ while IFS= read -r line; do
echo "$line"
done <a.txt
111
222
333 444
IFS
環境変数はinternal fieled separatorの省略で、 情報を分離するために利用される文字 が格納されています。read
コマンドはシェルのビルドインコマンドです。
$ type read
read is a shell builtin
標準入力で受け取った情報を IFS
環境変数に設定されている文字列で自動的に分割した後、引数で与えられた変数名(ここではline
)に格納します。
IFS= read
とすることで、一時的に区切り文字列を無視するようにしています。
IFS
環境変数を覗いてみる
では IFS
環境変数とはどのような値なのでしょうか?
頑張って覗けるだけ覗いてみます。
普通に echo
してみます。(ここでは -n
オプションを指定して、echo
コマンド自身が最後出力する改行文字を抑制しています。)
$ echo -n "$IFS"
なにか出力されていそうですがわかりませんね。
文字列を [...]
で囲んでみます。
$ echo -n "[$IFS]"
[
]
改行文字を含んでいるようです。
文字数がいくつか確認してみます。
# wc で文字数を確認
$ echo -n "$IFS" | wc -c
3
# @に置換してみる
$ echo -n "$IFS" | sed -z 's/./@/g'
@@@
どうやら3文字ですね。
ファイルに出力してみます。
$ echo -n "$IFS" > hoge
$ ls -l hoge
-rw-r--r-- 1 root root 3 Feb 7 11:07 hoge
3byte。
vi
で開くと更にわかりますが、これはスペース、タブ、改行の3つから構成されています。
ひとこと
while read
でのインデント消える問題の解消から IFS
環境変数の話へと発展してしまいました。
ディスカッション
コメント一覧
まだ、コメントがありません