Como faço para escapar o caractere curinga / asterisco no bash?
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"?
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:
- expansão de parâmetros
- 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"