Como obter bash para não tratar [como um caractere de teste ao usar a substituição de comando? [duplicado]

0

Como posso obter uma saída não modificada de $() no bash?

Eu preciso que o bash retorne os resultados da substituição do comando (via $(command) ou 'command' ), mas o bash trata o colchete esquerdo como o test incorporado e avalia o texto.

> echo "This shows an IP in brackets [127.0.0.1] when not in the command substitution context."
This shows an IP in brackets [127.0.0.1] when not in the command substitution context.

> echo $(echo "This should show an IP in brackets [127.0.0.1] but instead evaluates to '1'.")
This should show an IP in brackets 1 but instead evaluates to '1'.

> echo $(echo "The subtle addition of a space causes [127.0.0.1 ] to behave differently.")
The subtle addition of a space causes [127.0.0.1 ] to behave differently.

Antecedentes

Por favor, note que o uso de echo acima para fornecer um exemplo mínimo é apenas isso; meu uso final incluirá a saída de ping ou tracert para mostrar o IP de um host visto por esse host (isto é, respeitando quaisquer entradas de hosts). Nesse uso, tenho pouco controle sobre a string que está sendo enviada pelo comando.

> grep -E "^[^#].*stackoverflow" /c/Windows/System32/drivers/etc/hosts
127.0.0.1 stackoverflow.com

> tracert -h 1 -w 1 stackoverflow.com | awk '/Tracing/'
Tracing route to stackoverflow.com [127.0.0.1]

> ping -n 1 -w 1 stackoverflow.com | awk '/Pinging/'
Pinging stackoverflow.com [127.0.0.1] with 32 bytes of data:

# Using dig or nslookup would show a real IP rather than the forced IP from the hosts entry.
> dig @ns1 +nocmd stackoverflow.com +noall +answer
stackoverflow.com.      118     IN      A       151.101.129.69
stackoverflow.com.      118     IN      A       151.101.193.69
stackoverflow.com.      118     IN      A       151.101.1.69
stackoverflow.com.      118     IN      A       151.101.65.69

> echo $(ping -n 1 -w 1 stackoverflow.com | awk '/Pinging/')
Pinging stackoverflow.com 1 with 32 bytes of data:

> echo $(ping -n 1 -w 1 stackoverflow.com | awk '/Pinging/ {print $3}')
1

> ping -n 1 -w 1 stackoverflow.com | awk '/Pinging/ {print $3}'
[127.0.0.1]
    
por BQ. 07.09.2018 / 01:12

1 resposta

3

O problema é que a substituição do comando não é citada. Quando a substituição de comando usa a saída do comando echo como argumento para o segundo comando echo , os resultados do comando são submetidos à divisão de palavras e globulação de arquivos. Como apontado nos comentários, os caracteres entre colchetes, [127.0.0.1] , corresponderão a qualquer arquivo cujo nome seja exatamente um caractere e seja um dos 1 , 2 , 7 ou 0 (o padrão corresponderia a . apenas o shell ignora os links de diretório . e .. ). Quando criei um arquivo chamado 1 , consegui replicar seu resultado.

Para evitar que os resultados da substituição de comando sejam submetidos a globbing, você deve colocá-lo entre aspas duplas:

echo "$(echo "This will show an IP address in square brackets: [127.0.0.1]")"

Veja também os seguintes artigos relacionados da Wiki de Greg's (particularmente o primeiro que cobre a necessidade de citações duplas dentro e fora da substituição de comando):

por 07.09.2018 / 02:02