Pergunta

por exemplo.

me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR

e usando o "\" caractere de escape:

me$ FOO="BAR \* BAR"
me$ echo $FOO
BAR \* BAR

Estou, obviamente, fazer algo estúpido.

Como faço para obter a saída "BAR * BAR"?

Foi útil?

Solução

Citando ao definir $ FOO não é suficiente. Você precisa citar a referência da variável assim:

me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR

Outras dicas

RESPOSTA BREVE

Como outros - você deve sempre citar as variáveis ??para prevenir comportamento estranho. Portanto, use echo "$ foo" em vez de apenas echo $ foo .

resposta longa

Eu acho que este exemplo mandados de mais explicações porque há mais acontecendo do que parece no rosto dela.

Posso ver onde sua confusão vem porque depois que você correu seu primeiro exemplo você provavelmente pensou para si mesmo que o reservatório é, obviamente, fazer:

  1. expansão de parâmetros
  2. expansão Matrícula

Assim, desde o seu primeiro exemplo:

me$ FOO="BAR * BAR"
me$ echo $FOO

Depois de expansão de parâmetros é equivalente a:

me$ echo BAR * BAR

E após a expansão filename é equivalente a:

me$ echo BAR file1 file2 file3 file4 BAR

E se você apenas digitar echo BAR * BAR na linha de comando, você verá que eles são equivalentes.

Portanto, você provavelmente pensou para si mesmo "se eu escapar da *, eu posso evitar a expansão filename"

Assim, a partir de seu segundo exemplo:

me$ FOO="BAR \* BAR"
me$ echo $FOO

Depois de expansão de parâmetros deve ser equivalente a:

me$ echo BAR \* BAR

E após a expansão filename deve ser equivalente a:

me$ echo BAR \* BAR

E se você tentar digitar "echo BAR \ * BAR" diretamente na linha de comando ele vai realmente imprimir "BAR * BAR" porque a expansão filename é impedido pela fuga.

Então, por que utilizar $ foo não trabalho?

É porque existe uma terceira expansão que ocorre - Citar remoção. A partir da remoção manual do bash citação é:

Após as expansões anteriores, todos ocorrências não cotadas dos personagens ‘\’, ‘'’ E ‘'’ que não resultou a partir de uma das expansões acima são removida.

Então, o que acontece é quando você digita o comando diretamente na linha de comando, o caractere de escape não é o resultado de uma expansão anterior para BASH remove-lo antes de enviá-lo para o comando echo, mas na 2ª exemplo, o "\ *" foi o resultado de uma expansão de parâmetros anterior, por isso não é removido. Como resultado, eco recebe "\ *" e é isso que ele imprime.

Observe a diferença entre o primeiro exemplo -. "*" Não está incluído nos personagens que serão removidos por Citar Remoção

Espero que este sentimento marcas. No final, a conclusão da mesma - basta usar aspas. Eu apenas pensei que eu ia explicar por que escapa, o que logicamente deve funcionar se único parâmetro e expansão Matrícula estão em jogo, não funcionou.

Para uma explicação completa das expansões festança, referem-se:

http://www.gnu.org/software/ bash / Manual / bashref.html # Shell-Expansões

Vou acrescentar um pouco a esta discussão antiga.

Normalmente, você usaria

$ echo "$FOO"

No entanto, eu tive problemas, mesmo com esta sintaxe. Considere o seguinte script.

#!/bin/bash
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"

O * precisa ser passado verbatim para curl, mas irão surgir os mesmos problemas. O exemplo acima não irá funcionar (ele se expandirá para nomes de arquivos no diretório atual) e nem vai \*. Você também não pode citar $curl_opts porque ele vai ser reconhecido como uma opção única (inválida) para curl.

curl: option -s --noproxy * -O: is unknown
curl: try 'curl --help' or 'curl --manual' for more information

Portanto, eu recomendaria o uso da variável bash $GLOBIGNORE para evitar a expansão filename completamente se aplicada ao padrão global, ou usar o set -f embutido bandeira.

#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"  ## no filename expansion

A aplicação para o seu exemplo original:

me$ FOO="BAR * BAR"

me$ echo $FOO
BAR file1 file2 file3 file4 BAR

me$ set -f
me$ echo $FOO
BAR * BAR

me$ set +f
me$ GLOBIGNORE=*
me$ echo $FOO
BAR * BAR
FOO='BAR * BAR'
echo "$FOO"
echo "$FOO"

Pode valer a pena entrar no hábito de usar printf em vez echo na linha de comando.

Neste exemplo, ele não dá muito benefício, mas ele pode ser mais útil com saída mais complexa.

FOO="BAR * BAR"
printf %s "$FOO"
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top