Perché usare le virgolette doppie in un test [[]]?


23

Diciamo che abbiamo 2 numeri interi in uno script bash:

value1=5
value2=3

Allora perché dobbiamo usare le virgolette doppie in caso di test? Per esempio:

if [[ "$value1" -eq "$value2" ]]

Perché non usare solo quanto segue?

if [[ $value1 -eq $value2 ]]

Per me, le doppie virgolette non hanno alcun senso.


5
La citazione nella shell ha poco a che fare con le stringhe (come nei tipi di dati.) Si tratta davvero di impedire alla shell di eseguire la suddivisione delle parole (e altri tipi di espansioni.)
filbranden,

13
Mentre, come ha sottolineato Terdon, non è necessario citare anche le variabili in questo costrutto specifico (e, ovviamente, con valori di una parola ovunque), vorrei dare il consiglio di citare sempre i tuoi parametri. Sai davvero in quali contesti puoi lasciare le variabili non quotate? Il motivo per citare del tutto, anche se non è necessario con 5e 3, è la manutenibilità. I valori potrebbero cambiare in seguito e gli errori risultanti potrebbero non essere ovvi.
Peter - Ripristina Monica il

2
@sudodus Non credo sia vero [[ ]], solo per [ ].
Benjamin W.

1
Hai ragione, @BenjaminW. La divisione delle parole non è l'unico caso per cui è una buona idea usare le virgolette doppie per le variabili. C'è anche il caso in cui una variabile è vuota. Ciò renderà la dichiarazione in [] non riuscita (ad esempio [2 -eq] con un errore, ma [[]] non è vulnerabile (come nel caso della divisione delle parole).
sudodus,

2
@marcelm, Bash, ksh e Zsh hanno variabili intere e al [[ ]]loro interno costringono gli operandi -eqa numeri interi.
ilkkachu,

Risposte:


7

Suddivisione delle parole.

Questo esempio è molto improbabile, ma possibile , quindi se vuoi codificare in modo difensivo, copri le tue tracce con le virgolette:

$ set -x
$ value1=5
+ value1=5
$ value2=3
+ value2=3
$ [ $value1 -eq $value2 ]
+ '[' 5 -eq 3 ']'

OK, tutto bene finora. Gettiamo la chiave negli ingranaggi:

$ IFS=456
+ IFS=456
$ [ $value1 -eq $value2 ]
+ '[' '' -eq 3 ']'
bash: [: : integer expression expected

Ops.

$ [ "$value1" -eq "$value2" ]
+ '[' 5 -eq 3 ']'

Ahh.


2
Ma OP utilizza doppie parentesi, quindi non ha luogo alcuna divisione di parole.
user000001

5
Sì, questo non è rilevante per il [[ ]]costrutto di Bash .
terdon

1
Eh? [ $value1 -eq $value2 ]con un vuoto value1sarebbe '[' -eq 3 ']'senza ''il lato sinistro.
Charles Duffy,

Anche io sono stato sorpreso, ma ci sono le prove.
Glenn Jackman,

1
Questa risposta non è direttamente correlata alla domanda. Sono sorpreso che sia stato accettato. Impostazione come wiki della comunità.
Glenn Jackman,

35

In realtà non hai bisogno delle virgolette qui. Questo è uno dei pochissimi casi in cui è sicuro usare una variabile non quotata. Puoi confermarlo con set -x:

$ var1=""
$ var2="3"
$ set -x
$ if [[ $var1 -eq $var2 ]]; then echo "match!"; else echo "no match!"; fi
+ [[ '' -eq 3 ]]
+ echo 'no match!'
no match!
$ if [[ "$var1" -eq "$var2" ]]; then echo "match!"; else echo "no match!"; fi
+ [[ '' -eq 3 ]]
+ echo 'no match!'
no match!

Come puoi vedere sopra, le versioni citate e non quotate del test vengono risolte esattamente con la stessa cosa da bash. Lo stesso dovrebbe valere per zshe, credo, qualsiasi altra shell che supporti l' [[ ]]operatore.

Si noti che questo non è il caso del più portatile [ ]:

$ if [ $var1 -eq $var2 ]; then echo "match!"; else echo "no match!"; fi
+ '[' -eq 3 ']'
sh: [: -eq: unary operator expected
+ echo 'no match!'
no match!

Il [ ]costrutto, a differenza di [[ ]]quello, richiede un preventivo.


Alcuni link utili per saperne di più su quando e perché è richiesta la quotazione:


In questo caso con variabili intere sarebbe meglio dichiararle come tali. declare -i var1=è 0quando valutato.
Freddy,

4
Si noti che si -eqtratta di un confronto aritmetico , quindi è anche possibile lasciare l' $out (in [[ .. ]]) e scrivere [[ a -eq b ]]. Con il confronto delle stringhe, $ovviamente , è necessario il[[ $a = $b ]]
ilkkachu il

2
@ user000001 buon punto. Anche se, ovviamente, è molto probabile che tu li voglia espandere. Ad esempio, mi aspetto che questo sia un match: var1="afoob"; var2="a*b"; [[ $var1 = $var2 ]] && echo match. Se vuoi usare i personaggi glob senza che agiscano come glob in un contesto sconvolgente (come il [[ ]]), allora devi citare, sì.
terdon

3
@ilkkachu, questo mi sorprende. Ho pensato che le variabili "nude" sarebbero state considerate solo all'interno di un indice di matrice o ((...))o $((...). Sembra funzionare, ma (vecchio scontroso, abilita) Non mi piace.
Glenn Jackman,

1
@glennjackman, beh, mi dispiace essere quello che te lo dice, ma sì, anche gli operandi -eqe gli amici all'interno [[ ]]sono contesti aritmetici. :) (Correlato: Espansione automatica variabile all'interno del comando bash [[]] )
ilkkachu,

17

Anche se le doppie virgolette non sono necessarie, i motivi per usarle sono:

  • Buone pratiche / abitudine: in questo caso non sono necessarie, ma in generale le doppie virgolette servono per evitare la divisione non intenzionale delle parole.
  • Perché value1e value2sono variabili e potresti non sapere cosa contengono. Altrimenti potresti anche chiedere: "Perché preoccuparsi delle variabili invece di controllare if [[ 5 -eq 3 ]]? O prenderlo ulteriormente, perché preoccuparsi del iftutto quando sai già che 5 non è uguale a 3? Spesso è meglio essere difensivi. (È vero che la divisione delle parole non accadrà [[, ma i casi in cui la divisione delle parole non si verificano sono rari. Ancora una volta, vedi il primo punto.)

1

Non direttamente correlato alla tua domanda, ma io uso

if (($ value1 == $ value2)); poi

quando comparo i numeri, ma anche lì non devi usare le virgolette.


2
if (( value1 == value2 )); then. In contesti aritmetici, non è nemmeno necessario $. Questa domanda, tuttavia, sembra concentrarsi sulle variabili utilizzate nei [[ ... ]]test.
Kusalananda

1
Lo so. Ma sinceramente non uso questa funzione perché voglio che i miei nomi delle variabili siano coerenti e quindi usi $ come prefisso per tutto il tempo.
spasso

1

Hai assolutamente ragione!

La citazione tra parentesi quadre doppie non ha alcun senso, almeno in questo caso.

Ma dal momento che uso le doppie virgolette quotidianamente, soprattutto per le espressioni a parentesi quadre singole, passando argomenti a funzioni e script, nonché a volte assegnazione di variabili (che è completamente inutile per le semplici delcarazioni), credo che alcune persone, almeno lo faccio, scrivere istintivamente doppie virgolette attorno a espansioni variabili .

La doppia citazione può darti un senso di saggezza. È come tornare a casa dove ci sono le doppie virgolette. - D. Kummer

Un vantaggio di fare doppie citazioni di conseguenza e comprensibilmente - ma solo se ha senso - è che i colleghi che sono nuovi a bash possono imparare a scrivere script più stabili . Accentua anche il fatto che l'arte dell'elaborazione dei dati con bash riguarda principalmente la separazione dei flussi di dati (comprese le variabili) per i separatori di campo e il loro instradamento attraverso i filtri . Non appena i tuoi blocchi di dati sono separati dallo stream, tienili insieme con le doppie virgolette!

Un altro vantaggio potrebbe essere la migliore leggibilità degli script bash con stringhe tra virgolette doppie all'interno di un editor di evidenziazione del codice .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.