Enquanto aprendia o script bash através de um Guia do Iniciante , tentei escrever algumas linhas de código no .sh
arquivo, criado no TextEdit no macOS Yosemite e executá-lo usando o comando bash \path\to\script\file\example_script.sh
bash Terminal.
Linha de código que eu testei pela primeira vez:
echo “The path to my home directory is: $HOME”
Saída padrão (stdout) no Terminal:
“The path to my home directory is: ??
em vez de obter:
The path to my home directory is: /Users/Ri$hi
Então, eu fiquei sabendo do curioso caso de "smart quotes"
uma troca de pilha e joguei com alguns combos engraçados, como abaixo:
Linha de código que testei mais tarde:
Cenário 1:
echo “The path to my home directory is: $HOME (foo) bar”
stdout:
-bash: syntax error near unexpected token `('
Cenário 2:
echo "The path to my home directory is: $HOME (foo) bar"
stdout:
The path to my home directory is: /Users/Ri$hi (foo) bar
Cenário 3:
echo “The path to my home directory is: $HOME” “(foo)” “bar”
stdout:
-bash: syntax error near unexpected token `('
Cenário 4:
echo "The path to my home directory is: $HOME" “(foo)” “bar”
stdout:
-bash: syntax error near unexpected token `('
Cenário 5:
echo “The path to my home directory is: $HOME” "(foo)" “bar”
stdout:
“The path to my home directory is: ?? (foo) “bar”
Então, pensei por que não descobrir o motivo interativamente neste fórum.
NOTA: Terminal sempre exibe Citação duplo padrão "
quando Shift+ "é pressionado, mas permite exibir aspas inteligentes “ ”
através ⌘+ C, ⌘+ Voperação.
'
e ou"
conforme apropriado, quando aplicável. Eu também sugiro fortemente que você nunca use o TextEdit e, em vez disso, use um editor de código apropriado, por exemplo, Sublime Text.Respostas:
Há duas coisas acontecendo aqui: Primeiro, o bash reconhece as aspas simples ASCII simples
"
(código de caractere 0x22) como aspas duplas; ele não reconhece as aspas duplas à esquerda do unicode chique“
(unicode U + 201C, UTF-8 que codifica 0xe2809c) e a citação dupla à direita correspondente”
(unicode U + 201D, UTF-8 que codifica 0xe2809d) como algo diferente de seqüências aleatórias de bytes (ou talvez caracteres aleatórios, se estiver usando um código de idioma UTF-8). É isso que você deve perceber: no que diz respeito ao bash,“
e”
na verdade não são aspas , são apenas coisas que parecem aspas quando são impressas.A segunda complicação é que as aspas duplas unicode são caracteres multibyte; portanto, se o bash não estiver em um código de idioma UTF-8, ele poderá tratar alguns bytes de maneira diferente dos outros (!)
Para ver o efeito da primeira coisa, tente substituir cada ocorrência de aspas duplas pela string
WIBBLE
- outra sequência arbitrária que não tem significado especial para o shell:No primeiro comando (com aspas duplas ASCII), as aspas são analisadas e removidas pelo bash antes que os argumentos sejam passados para o
echo
comando e, portanto, não são impressos. Na segunda e na terceira (com aspas duplas sofisticadas e WIBBLE no lugar de aspas simples), elas são tratadas apenas como parte das strings a serem passadasecho
, e asecho
imprimem como parte de sua saída.Nos segundo e terceiro comandos (com aspas duplas e WIBBLE), o bash vê parênteses em uma parte não citada do comando (lembre-se: no que diz respeito ao bash, aspas extravagantes não são realmente aspas ), em um local onde eles não são permitidos pela sintaxe do shell e, portanto, reclama.
Aqui, algo mais estranho está acontecendo. No segundo comando, ele está procurando uma variável denominada
HOMEWIBBLE
, não a encontra, substituindo-a por uma em branco. No caso do primeiro, com aspas duplas, parece-me tratar cada byte da codificação UTF-8”
como um caractere separado, tratando o primeiro como parte do nome da variável (causando novamente a variável não encontrado) e, em seguida, basta passar o segundo e o terceiro bytes, fornecendo um caractere UTF-8 inválido, que é impresso como??
. Usar um dump hexadecimal para ter uma idéia melhor do que está acontecendo fornece:Observe que a primeira
“
passa bem e aparece no dump hexadecimal comoe2 80 9c
(a cotação dupla extravagante codificada UTF-8 esperada), mas depois disso é apenas80 9d
- a primeirae2
da segunda cotação extravagante foi comida de alguma forma! (BTW, o0a
no final é um avanço de linha, marcando o final da saída.) Para ver o que está acontecendo, deixe-me definir uma variável do shell comoHOME
+ o primeiro byte da codificação”
e observe o que acontece:... Então, o que está acontecendo: trata o primeiro byte da codificação de aspas duplas como parte do nome da variável, substitui-o (se definido) e passa apenas pelo segundo e terceiro bytes órfãos, deixando UTF inválido- 8) Não tenho certeza se isso é um bug do bash, estranheza de sua análise ou o quê.
De qualquer forma, os detalhes são bastante confusos, mas a explicação deve ser clara: não use aspas sofisticadas em seus scripts de shell; eles não vão funcionar direito. E o mesmo se aplica a aspas simples e outros sinais de pontuação unicode.
fonte
$ echo ”$HOME” | xxd -g1
recebo0000000: e2 80 9d 66 6f 6f 80 9d 0a
7 zeros inicialmente, em vez de 8, no seu caso. Qual poderia ser a razão por trás disso?echo
, eles são adicionadosxxd
para acompanhar onde você está (necessário ao descarregar arquivos grandes). Portanto, eles não deveriam estar relacionados ao bash ou às citações sofisticadas ... BTW, eu originalmente copiei esse comando final errado (corrigido agora) - mas a00000000
parte estava certa.