Os parâmetros de peixes são, como regra, escapados antes de serem injetados em comandos de peixes:
mqudsi@freebsd> echo hello > hello\ world.txt
mqudsi@freebsd> file (echo hello world.txt)
hello world.txt: ASCII text
No entanto, o resultado da expansão de colchetes não é escapado corretamente, _e_ não há uma maneira fácil de escapar para escapar manualmente, pois a introdução de aspas em torno do parâmetro quebra a expansão:
mqudsi@freebsd> echo -n hello\ {1,2,3}.txt\n
hello 1.txt
hello 2.txt
hello 3.txt
Como você pode ver, após o primeiro parâmetro, echo
está recebendo dois argumentos separados hello
e #.txt
, levando ao espaço extra na frente das palavras.
Colocar os argumentos entre aspas leva ao seguinte:
mqudsi@freebsd> echo -n "hello\ {1,2,3}.txt\n"
hello\ {1,2,3}.txt\n
Ao tentar contornar o problema inserindo aspas com escape na string original (presumindo-se que o conteúdo da string não está escapando após a substituição e antes da injeção), as aspas escapam corretamente, evitando o resultado desejado:
mqudsi@freebsd> echo -n \"hello\ {1,2,3}.txt\n\" "hello 1.txt " "hello 2.txt " "hello 3.txt
"
Parece que a expansão do parâmetro está acontecendo após o estágio de divisão do argumento.
echo
está recebendo dois argumentos separados hello e # .txt, levando ao espaço extra na frente das palavras.
Não concordo com esse diagnóstico. echo
está recebendo 3 argumentos (cada um terminando com \n
), que echo
devidamente imprime com um espaço entre eles. Não vejo nenhum bug aqui.
Aqui está o que eu faço para depurar argumentos:
~> printf '«%s»' hei\ {1,2,3}.txt\n
«hei 1.txt
»«hei 2.txt
»«hei 3.txt
»⏎
Aqui está o que eu faço para depurar argumentos:
Eu uso string escape
, ou seja,
> string escape -- hello\ {1,2,3}.txt\n
hello\ 1.txt\n
hello\ 2.txt\n
hello\ 3.txt\n
o que significa que você realmente consegue o que eu esperava. Você obtém o argumento completo com "1", depois com "2" e, em seguida, com "3". O argumento completo inclui apenas uma nova linha.
@mqudsi : Presumo que o que está
(command)
) em nova linha. Isso significa que \n
aqui não tem nenhum significado especial depois de ser substituído por um caractere de nova linha. É "um personagem", no que diz respeito ao resto. Não precisamos _escape_ do personagem, apenas não executamos a divisão.Ou em file (echo hello world.txt)
, o "hello world.txt" _não_ escapou para hello\ world.txt
, não é dividido porque não há nova linha. Se você tiver um arquivo chamado hello\nworld.txt
, isso teria problemas semelhantes ao problema do bash com espaços.
echo
insere espaços entre seus argumentos (se "-s" não foi fornecido). Isso é o que está causando o recuo estranho - porque os espaços acontecem logo após a nova linha.Isso significa que se você deseja ter a saída
hello 1.txt
hello 2.txt
hello 3.txt
use echo -s
ou printf '%s\n' hello\ {1,2,3}.txt
.
Acredito que isso seja um mal-entendido, e não um bug. Estou correcto?
Desculpe, pessoal! Eu estava tentando encontrar uma reprodução mínima para um problema e estava confuso com algo completamente diferente. Eu entendi o comportamento de expansão de parâmetro errado, em particular, eu o confundi com parallel
ou xargs
com um limite de 1, ou seja, presumi que echo {1,2,3}
se expandiria para 3 comandos com 1 argumento cada e não 1 comando com 3 argumentos.
Obrigado por me esclarecer.