Como desabilitar a divisão de palavras durante a substituição de comandos?

2

Como posso desabilitar a divisão de palavras durante a substituição de comandos? Aqui está um exemplo simplificado do problema:

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

O que eu quero é que echo $(cat test.txt) (ou alguma variante do que inclui a subsituição de comando) produza hello\nworld .

Encontrei o link que diz na parte inferior If the substitution appears within double quotes, word splitting and filename expansion are not performed on the results. mas parece não conseguir entender isso. Eu teria pensado que um dos exemplos que eu já tentei se conformava com essa regra, mas eu acho que não.

    
por Paymahn Moghadasian 22.08.2018 / 22:09

2 respostas

10

Ter um literal \n get alterado para uma nova linha não é sobre a divisão de palavras, mas echo processando a barra invertida. Algumas versões de echo fazem isso, outras não ... O echo do Bash não processa escape de barra invertida por padrão (sem a opção -e flag ou xpg_echo ), mas, por exemplo, as versões de dash e Zsh de echo do.

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

Use printf :

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

Veja também: Por que o printf é melhor que o eco?

Independentemente disso, você deve colocar as aspas ao redor da substituição do comando para evitar a divisão de palavras e globbing em shells semelhantes a sh. (zsh só faz a divisão de palavras (não globbing) após a substituição de comando (não sobre o parâmetro ou expansões aritméticas), exceto no modo sh.)

    
por 22.08.2018 / 22:15
0

O eco implementado por zsh interpreta as seqüências de escape por padrão. A solução mais simples é:

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

ou

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

A solução correta é usar printf:

$ printf '%s\n' "$(<test.txt)"
    
por 23.08.2018 / 02:57