6

forシェルで使用して、スペースを含むファイル名を反復処理しようとしています。使用できるスタックオーバーフローの質問を読みましたが、IFS=$'\n'うまくいくようです。次に、答えの1つへのコメントを読んで、使用できるbash以外のシェルと互換性があるようにしIFS=$(echo -e '\n')ました。

前者は機能しますが、後者は機能しません。コメントは数回賛成されています。出力を確認したところ、変数に改行が含まれていないようです。

#!/bin/sh

IFS=$(echo -e '\n')
echo -n "$IFS" | od -t x1
for file in `printf 'one\ntwo two\nthree'`; do
    echo "Found $file"
done

echo

IFS=$'\n'
echo -n "$IFS" | od -t x1
for file in `printf 'one\ntwo two\nthree'`; do
    echo "Found $file"
done


出力は、最初のフィールド区切り文字が欠落していることを示しています。

0000000
Found one
two two
three


しかし、2番目に適切です:

0000000 0a
0000001
Found one
Found two two
Found three


私の質問と重複している場合と重複していない場合がある回答済みの質問を見つけました:
linux - IFS を改行で分割するように設定する場合、バックスペースを含める必要があるのはなぜですか? - スタックオーバーフロー

そこで議論されていることを行うことに危険はありますIFS=$(echo -en '\n\b')か? \bそれはIFSにaを追加するためです(私はチェックしました)。\bファイル名にaが含まれることはありますか? コードで誤ってファイル名を分割したくありません。

forまた、ループ後に IFS の復元を適切に処理する方法に関する推奨事項はありますか? 一時変数に保存するか、サブシェルで IFS と for ステートメントを実行する必要がありますか? (そしてそれを行う方法は?)ありがとう

4

3 に答える 3

5

@DigitalTraumaが正しく書いたように、改行はコマンド置換によって削除されるため、別のPOSIX準拠の方法を使用する必要があります。

IFS='
'

改行を書き込み、それに割り当てます。シンプルで効果的。

2 行にまたがる割り当てが気に入らない場合はprintf、代わりに使用できます。

IFS="$(printf '\n')"
于 2014-10-02T08:32:00.550 に答える