Qual è la differenza tra il file apple grep e il file "apple" grep?


22

Qual è la differenza tra grep apple filee grep "apple" file? Cosa fanno le virgolette? Entrambi sembrano funzionare e fare esattamente la stessa cosa (visualizzare la stessa linea).

Risposte:


45

Le virgolette hanno un effetto su quali caratteri la tua shell considera speciali e hanno un significato sintattico. Nel tuo esempio questo non fa differenza perché applenon contiene tali caratteri.

Ma considera un altro esempio: grep apple tree filecercherà la parola applenei file treee file, mentre grep "apple tree" filecercherà la parola apple treenel file file. Le virgolette indicano a bash che lo spazio delle parole in "apple tree"non avvia un nuovo parametro ma deve far parte del parametro corrente. grep apple\ tree fileprodurrebbe lo stesso risultato, perché \dice a bash di ignorare il significato speciale del personaggio seguente e trattarlo letteralmente.


2
Questo è visibile anche con i caratteri jolly. Se lo fai grep a*b equations.txtallora cercherà a*b, a meno che non ci sia un file nella directory corrente che inizia con ae termina con b, nel qual caso (perché (ba) sh espanderà i nomi dei file sulla riga di comando) grep verrà chiamato con completare parametri diversi, con risultati diversi. Questo di solito è più un problema con find, poiché un comando simile find . -name *.txtcomporterà un comportamento imprevisto, se esiste un file txt nella directory corrente. In questo caso è meglio usare le virgolette.
SztupY,

4
Un altro punto importante è la differenza tra virgolette doppie ( ") e virgolette singole ( '). Le virgolette singole impediscono l'interpretazione di alcuni caratteri come $, mentre le virgolette doppie consentono l'interpretazione. Ad esempio grep '${USER}'cercherà il testo ${USER}, mentre grep "${USER}"cercherà il testo che USERcontiene la variabile (ad esempio johnstacen).
Paddy Landau,

23

Le virgolette doppie consentono la valutazione, le virgolette singole impediscono la valutazione, nessuna virgola consente l'espansione di caratteri jolly, se utilizzata sulla riga di comando. Come esempi inventati:

[user@work test]$ ls .
A.txt B.txt C.txt D.cpp

# The following is the same as writing echo 'A.txt B.txt C.txt D.cpp'
[user@work test]$ echo *
A.txt B.txt C.txt D.cpp

[user@work test]$ echo "*"
*

[user@work test]$ echo '*'
*

# The following is the same as writing echo 'A.txt B.txt C.txt'
[user@work test]$ echo *.txt
A.txt B.txt C.txt

[user@work test]$ echo "*.txt"
*.txt

[user@work test]$ echo '*.txt'
*.txt

[user@work test]$ myname=is Fred; echo $myname
bash: Fred: command not found

[user@work test]$ myname=is\ Fred; echo $myname
is Fred

[user@work test]$ myname="is Fred"; echo $myname
is Fred

[user@work test]$ myname='is Fred'; echo $myname
is Fred

Comprendere il modo in cui funzionano le citazioni è fondamentale per comprendere Bash. Per esempio:

# for will operate on each file name separately (like an array), looping 3 times.
[user@work test]$ for f in $(echo *txt); do echo "$f"; done;
A.txt
B.txt
C.txt

# for will see only the string, 'A.txt B.txt C.txt' and loop just once.
[user@work test]$ for f in "$(echo *txt)"; do echo "$f"; done;
A.txt B.txt C.txt

# this just returns the string - it can't be evaluated in single quotes.
[user@work test]$ for f in '$(echo *txt)'; do echo "$f"; done;
$(echo *txt)

È possibile utilizzare virgolette singole per passare un comando tramite una variabile. Le virgolette singole impediranno la valutazione. Le virgolette doppie verranno valutate.

# This returns three distinct elements, like an array.
[user@work test]$ echo='echo *.txt'; echo $($echo)
A.txt B.txt C.txt

# This returns what looks like three elements, but it is actually a single string.
[user@work test]$ echo='echo *.txt'; echo "$($echo)"
A.txt B.txt C.txt

# This cannot be evaluated, so it returns whatever is between quotes, literally.
[user@work test]$ echo='echo *.txt'; echo '$($echo)'
$($echo)

Puoi usare virgolette singole tra virgolette doppie e puoi usare virgolette doppie tra virgolette doppie, ma le virgolette doppie tra virgolette singole non devono essere eseguite (senza evitarle) non verranno valutate, verranno interpretate letteralmente. Le virgolette singole all'interno di virgolette singole non devono essere eseguite (senza sfuggirle).

Per utilizzare efficacemente Bash devi acquisire una conoscenza approfondita delle citazioni. Molto importante!

Come regola generale, non uso le virgolette se voglio che Bash espanda qualcosa in elementi (come un array), uso virgolette singole per stringhe letterali che non devono essere modificate e faccio un uso liberale di virgolette doppie per le variabili che probabilmente restituiranno qualsiasi tipo di stringa. Questo per garantire che vengano preservati spazi e caratteri speciali.


Come useresti le virgolette doppie tra virgolette doppie ??? È un errore di battitura? E perché invece dovrei evitare le doppie virgolette all'interno delle virgolette singole? Immagino che tu abbia confuso le frasi forse?
Byte Commander

@ByteCommander Sì, il concetto di virgolette doppie inserite tra virgolette doppie viene usato abbastanza comunemente - vedi questo post per un esempio di lavoro di rilievo. Di solito viene fatto per proteggere le stringhe che contengono spazi, spesso rispetto alle stringhe del percorso. Le virgolette doppie possono essere utilizzate tra virgolette singole con o senza escape, ma verranno interpretate letteralmente, cioè non porteranno alla valutazione. Chiarirò questo punto nel post.
AsymLabs
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.