Cosa rende l'utilità dell'interprete bash interpretare in modo diverso le virgolette standard e intelligenti, presenti in uno script di shell, creato in TextEdit?

3

Durante l'apprendimento degli script di bash attraverso la Guida per principianti , ho provato a scrivere alcuni linee di codice nel file .sh , create in TextEdit su macOS Yosemite ed eseguendole usando il comando bash \path\to\script\file\example_script.sh nel terminale bash.

Linea di codice che ho testato per la prima volta:

echo “The path to my home directory is: $HOME”

Output standard (stdout) nel terminale:

“The path to my home directory is: ??

invece di ottenere:

The path to my home directory is: /Users/Ri$hi

Poi, ho avuto modo di conoscere il curioso caso di "smart quotes" da un stackexchange , e giocato con alcune combo divertenti, come di seguito:

Linea di codice che ho provato in seguito:

Scenario 1:

echo “The path to my home directory is: $HOME (foo) bar”

stdout:

-bash: syntax error near unexpected token '('

Scenario 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

Scenario 3:

echo “The path to my home directory is: $HOME” “(foo)” “bar”

stdout:

-bash: syntax error near unexpected token '('

Scenario 4:

echo "The path to my home directory is: $HOME" “(foo)” “bar”

stdout:

-bash: syntax error near unexpected token '('

Scenario 5:

echo “The path to my home directory is: $HOME” "(foo)" “bar”

stdout:

“The path to my home directory is: ?? (foo) “bar”

Quindi, ho pensato perché non scoprire il motivo in modo interattivo su questo forum.

NOTA: il terminale visualizza sempre la doppia virgoletta standard " quando viene premuto Maiusc + ", ma consente di visualizzare virgolette doppie intelligenti “ ” fino a + C , + V operazione.

    
posta Rishi Khanna 30.08.2017 - 20:35
fonte

1 risposta

9

Ci sono due cose che succedono qui: in primo luogo, bash riconosce la doppia virgoletta ASCII normale, " (codice carattere 0x22) come una doppia citazione; non riconosce l'unicode di fantasia left double-quote, (Unicode U + 201C, codifica UTF-8 0xe2809c) e la corrispondente doppia virgola destra, (unicode U + 201D, codifica UTF-8 0xe2809d) come qualcosa di diverso da sequenze casuali di byte (o forse come caratteri casuali, se si utilizza un locale UTF-8). Questa è la cosa fondamentale da realizzare: per quanto riguarda bash, e non sono effettivamente virgolette , sono solo cose che assomigliano a virgolette quando sono stampato.

La seconda complicazione è che le virgolette unicode sono caratteri multibyte, quindi se bash non è in un locale UTF-8 potrebbe trattare alcuni dei byte in modo diverso rispetto ad altri (!)

Per vedere l'effetto della prima cosa, prova a sostituire ogni occorrenza di una virgola doppia con la stringa WIBBLE - un'altra sequenza arbitraria che non ha alcun significato speciale per la shell:

$ echo "The path to my home directory is: $HOME bar"
The path to my home directory is: /Users/gordon bar
$ echo “The path to my home directory is: $HOME bar”
“The path to my home directory is: /Users/gordon bar”
$ echo WIBBLEThe path to my home directory is: $HOME barWIBBLE
WIBBLEThe path to my home directory is: /Users/gordon barWIBBLE

Nel primo comando (con virgolette ASCII), le virgolette vengono analizzate e rimosse da bash prima che gli argomenti vengano passati al comando echo e quindi non stampati. Nella seconda e terza (con doppie virgolette fantasiose e WIBBLE al posto di virgolette semplici), vengono semplicemente considerate come parte delle stringhe da passare a echo , quindi echo le stampa come parte del suo output.

$ echo "The path to my home directory is: $HOME (foo) bar"
The path to my home directory is: /Users/gordon (foo) bar
$ echo “The path to my home directory is: $HOME (foo) bar”
-bash: syntax error near unexpected token '('
$ echo WIBBLEThe path to my home directory is: $HOME (foo) barWIBBLE
-bash: syntax error near unexpected token '('

Nel secondo e nel terzo comando (con virgolette fantasiose e WIBBLE), bash vede parentesi in una porzione non quotata del comando (ricorda: per quanto riguarda bash, le virgolette sono in realtà non cita ), in un luogo in cui non sono consentiti dalla sintassi della shell e, pertanto, si lamentano.

$ echo “The path to my home directory is: $HOME”
“The path to my home directory is: ??
$ echo WIBBLEThe path to my home directory is: $HOMEWIBBLE
WIBBLEThe path to my home directory is:

Qui sta succedendo qualcosa di strano. Nel secondo comando, cerca una variabile denominata HOMEWIBBLE , non trovandola, quindi sostituendola con spazio vuoto. Nel caso del primo, con le doppie virgolette fantasiose, mi sembra che tratti ogni byte della codifica UTF-8 di come carattere separato, trattando il primo come parte del nome della variabile (di nuovo causando la mancata rilevazione della variabile), quindi passando semplicemente il secondo e il terzo byte, dando un carattere UTF-8 non valido, che viene stampato come ?? . Usando un dump esadecimale per avere una migliore idea di cosa sta succedendo dà questo:

$ echo “$HOME”
“??
$ echo “$HOME” | xxd -g1
00000000: e2 80 9c 80 9d 0a                                ......

Si noti che il primo passa per il fine e si presenta nel dump esadecimale come e2 80 9c (la doppia citazione fittizia con UTF-8 prevista), ma dopo questo è solo 80 9d - il primo e2 della seconda citazione fantasia è stata mangiata in qualche modo! (A proposito, il 0a alla fine è un avanzamento di riga, che segna la fine dell'output.) Per vedere cosa sta accadendo, fammi definire una variabile di shell come HOME + il primo byte della codifica di , e guarda cosa succede:

$ eval $'HOME\xe2=foo'
$ echo “$HOME”
“foo??
$ echo “$HOME” | xxd -g1
00000000: e2 80 9c 66 6f 6f 80 9d 0a                       ...foo...

... Ecco cosa sta succedendo: sta trattando il primo byte della codifica della doppia citazione come parte del nome della variabile, sostituendolo (se definito), e quindi passando semplicemente attraverso il secondo e il terzo byte orfani, lasciando UTF-8 non valido. Non sono sicuro che si tratti di un bug di base, di una stranezza del suo parsing o di cosa.

Comunque, i dettagli sono piuttosto disordinati, ma il take-away dovrebbe essere chiaro: non usare virgolette fantasiose negli script della shell; non funzioneranno correttamente. Lo stesso vale per le virgolette fantasia e altri segni di punteggiatura Unicode.

    
risposta data 30.08.2017 - 21:47
fonte

Leggi altre domande sui tag