コマンド置換を使用すると改行文字が失われるのはなぜですか?

コマンド置換を使用すると改行文字が失われるのはなぜですか?

以下のようにlink.txtというテキストファイルがあります。

link1
link2
link3

このファイルを1行ずつ繰り返し、各行で作業をしたいと思います。 whileループを使用してこれを行うことができることを知っていますが、学習しているのでforループを使用したいと思います。私は実際に次のコマンド置換を使用しました。

a=$(cat links.txt)

次に、このようなループを使用します。

for i in $a; do ###something###;done

私もこんなことができます。

for i in $(cat links.txt); do ###something###; done

私の問題は、catコマンドの出力を変数aに置き換えると、link1 link2とlink3の間の新しい行文字が削除され、空白に置き換えられることです。

echo $a

出力

リンク1リンク2リンク3

その後、forループを使用しました。コマンド置換を実行すると、新しい行は常に空白に置き換えられますか?

挨拶

ベストアンサー1

改行文字は特殊文字なので、ある時点で置き換えられます。これを保存するには、常に引用符を使用して解釈する必要があります。

$ a="$(cat links.txt)"
$ echo "$a"
link1
link2
link3

データを操作するたびに引用符が使用されるため、改行文字(\n)は常にシェルによって解釈され、そのまま残ります。特定の時点で使用することを忘れた場合、これらの特殊文字は失われます。

スペースを含む行にループを使用しても、同じ動作が発生します。たとえば、次のファイルが与えられた場合...

mypath1/file with spaces.txt
mypath2/filewithoutspaces.txt

出力は引用符を使用するかどうかによって異なります。

$ for i in $(cat links.txt); do echo $i; done
mypath1/file
with
spaces.txt
mypath2/filewithoutspaces.txt

$ for i in "$(cat links.txt)"; do echo "$i"; done
mypath1/file with spaces.txt
mypath2/filewithoutspaces.txt

引用符を使用したくない場合は、特殊なシェル変数を使用してシェルフィールド区切り文字(IFS)を変更できます。この区切り文字を改行文字に設定すると、ほとんどの問題を解決できます。

$ IFS=$'\n'; for i in $(cat links.txt); do echo $i; done
mypath1/file with spaces.txt
mypath2/filewithoutspaces.txt

完全性を期すためにコマンド出力置換に依存しない別の例がある。しばらくすると、ほとんどのユーザーはユーティリティの動作により、この方法がより安定していると考えることがわかりましたread

$ cat links.txt | while read i; do echo $i; done

read以下は、マニュアルページから抜粋した内容です。

読み取りユーティリティは標準入力から1行を読み取る必要があります。

read入力は 1 行ずつ行われるため、スペースが現れるたびに入力は中断されません。出力をパイプで接続すると、cat行がうまく繰り返されます。

編集する:人々catジェイソン・ライアン彼のコメントにもっと適切シェルからファイルを読み取る方法は、<前述のようにストリームリダイレクト()を使用することです。val0x00ffの答えはここにあります。しかし、質問は「ではないからシェルプログラミングでファイルを読み取って処理する方法「私の答えは、残りのものよりも引用行為に焦点を当てています。

おすすめ記事