コマンドの置換中に単語の区切りを無効にする方法は?

コマンドの置換中に単語の区切りを無効にする方法は?

コマンドの置換中に単語の区切りを無効にする方法は?以下は問題の簡単な例です。

午後4時/ユーザー/paymahn/ダウンロード
 ❯❯❯猫テスト.txt
こんにちは。\ n
 午後4時/ユーザー/paymahn/ダウンロード
 ❯❯❯ エコ$(cat test.txt)
こんにちは
世界
 午後4時/ユーザー/paymahn/ダウンロード
 ❯❯❯ echo "$(cat test.txt)"
こんにちは
世界
 午後4時1分/ユーザー/paymahn/ダウンロード
 ❯❯❯ echo "$(cat "test.txt" )"
こんにちは
世界

私が望むのはecho $(cat test.txt)(またはコマンド置換を含むいくつかのバリエーション)出力ですhello\nworld

私が見つけたhttps://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html一番下に書いてありますがIf the substitution appears within double quotes, word splitting and filename expansion are not performed on the results.とても理解できませんね。私が試した例の1つはそのルールに合うと思ったが、そうではないようだ。

答え1

リテラルを\n改行に変更することは、単語の分離ではなくechoバックスラッシュを処理することです。一部のバージョンはechoこれを行い、一部はそうではありません。 Bashはechoデフォルトではバックスラッシュエスケープを処理しませんが(-eフラグやxpg_echoオプションはありません)、例えばダッシュとZshのバージョンはecho処理します。

$ cat test.txt 
hello\nworld
$ bash -c 'echo "$(cat test.txt)"'
hello\nworld
$ zsh -c 'echo "$(cat test.txt)"'
hello
world

代わりに使用してくださいprintf

$ bash -c 'printf "%s\n" "$(cat test.txt)"'
hello\nworld
$ zsh -c 'printf "%s\n" "$(cat test.txt)"'
hello\nworld

また見なさい:なぜprintfがechoより優れているのですか?

それにもかかわらず、shなどのシェルでワードセパレータとワイルドカードを回避するには、コマンドの代わりに引用符を入れる必要があります。 (shモードを除いて、zshはコマンドの代入(引数または算術拡張ではない)時にのみトークン化(ワイルドカードではない)を実行します。)

答え2

echoのzsh実装は基本的にエスケープシーケンスを解釈します。最も簡単な解決策は次のとおりです。

$ echo -E "$(cat test.txt)"
hello\nworld

または

$ print -r "$(cat test.txt)"

正しい解決策はprintfを使用することです。

$ printf '%s\n' "$(<test.txt)"

関連情報