web-dev-qa-db-ja.com

コマンド置換中に単語分割を無効にする方法は?

コマンド置換中に単語分割を無効にするにはどうすればよいですか?問題の簡単な例を次に示します。

 4:00 PM/Users/paymahn/Downloads 
❯❯❯cattest.txt
 hello\nworld 
 4:00 PM/Users/paymahn/Downloads 
❯❯❯echo$(cat test.txt)
 hello 
 world 
 4:00 PM/Users/paymahn/Downloads 
❯❯❯echo " $(cat test.txt) "
 hello 
 world 
 4:01 PM/Users/paymahn/Downloads 
❯❯❯echo" $(cat "test。 txt ")" 
 hello 
 world 

私が欲しいのは、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つはその規則に準拠していると思いましたが、そうではないと思います。

3

リテラルの\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のようなシェルでの単語の分割やグロブを防ぐために、コマンド置換を引用符で囲む必要があります。 (zshは、shモードを除いて、コマンド置換時(パラメーターまたは算術展開時ではない)にのみワード分割(グロブではない)を行います。)

10
ilkkachu

Zshによって実装されたエコーは、デフォルトでエスケープシーケンスを解釈します。最も簡単な解決策は次のとおりです。

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

または

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

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

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