Quelle est la différence entre le fichier grep apple et le fichier grep «apple»?

22

Quelle est la difference entre grep apple fileet grep "apple" file? Que fait la mise entre guillemets? Ils semblent tous les deux fonctionner et font exactement la même chose (afficher la même ligne).

John Stacen
la source

Réponses:

45

Les guillemets ont un effet sur les caractères que votre shell considère spéciaux et ont une signification syntaxique. Dans votre exemple, cela ne fait aucune différence car applene contient pas de tels caractères.

Mais considérons un autre exemple: grep apple tree filerecherchera le mot appledans les fichiers treeet file, tandis que grep "apple tree" filerecherchera le mot apple treedans le fichier file. Les guillemets indiquent à bash que l'espace des mots dans "apple tree"ne démarre pas un nouveau paramètre mais doit faire partie du paramètre actuel. grep apple\ tree fileproduirait le même résultat, car \dit à bash de ne pas tenir compte de la signification spéciale du caractère suivant et de le traiter littéralement.

David Foerster
la source
2
Ceci est également visible avec des caractères génériques. Si vous le faites, grep a*b equations.txtil recherchera a*b, sauf s'il y a un fichier dans le répertoire courant commençant par a, et se terminant par b, auquel cas (parce que (ba) sh étendra les noms de fichiers sur la ligne de commande) grep sera appelé avec compléter différents paramètres, ce qui donne des résultats différents. C'est généralement plus un problème avec find, car une commande comme find . -name *.txtentraînera un comportement inattendu, s'il y a un fichier txt dans le répertoire courant. Il est préférable d'utiliser des guillemets dans ce cas.
SztupY
4
Un autre point important est la différence entre les guillemets doubles ( ") et les guillemets simples ( '). Les guillemets simples empêchent l'interprétation de certains caractères tels que $, tandis que les guillemets doubles permettent l'interprétation. Par exemple, grep '${USER}'va chercher le texte ${USER}, tandis que grep "${USER}"va chercher le texte que la variable USERcontient (par exemple johnstacen).
Paddy Landau,
23

Les guillemets doubles permettent l'évaluation, les guillemets simples empêchent l'évaluation, aucun guillemet ne permet l'expansion des caractères génériques lorsqu'ils sont utilisés en ligne de commande. Comme exemples artificiels:

[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

Comprendre le fonctionnement des citations est essentiel pour comprendre Bash. Par exemple:

# 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)

Vous pouvez utiliser des guillemets simples pour passer une commande via une variable. Les guillemets simples empêcheront l'évaluation. Les guillemets doubles seront évalués.

# 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)

Vous pouvez utiliser des guillemets simples à l'intérieur des guillemets doubles et vous pouvez utiliser des guillemets doubles à l'intérieur des guillemets doubles, mais les guillemets doubles à l'intérieur des guillemets simples ne doivent pas être effectués (sans les échapper) ne seront pas évalués, ils seront interprétés littéralement. Les guillemets simples entre guillemets simples ne doivent pas être effectués (sans les échapper).

Vous devrez acquérir une compréhension approfondie des devis pour utiliser efficacement Bash. Très important!

En règle générale, je n'utilise pas de guillemets si je veux que Bash développe quelque chose en éléments (comme un tableau), j'utilise des guillemets simples pour les chaînes littérales qui ne doivent pas être modifiées, et j'utilise généreusement des guillemets doubles pour les variables susceptibles de renvoyer tout type de chaîne. Il s'agit de garantir que les espaces et les caractères spéciaux seront préservés.

AsymLabs
la source
Comment utiliseriez-vous des guillemets doubles à l'intérieur de guillemets doubles ??? Est-ce une faute de frappe? Et pourquoi devrais-je plutôt échapper les guillemets doubles entre guillemets simples? Je suppose que vous avez peut-être mélangé les phrases?
Byte Commander
@ByteCommander Oui, le concept de guillemets doubles placés à l'intérieur de guillemets doubles est utilisé assez couramment - voir cet article pour un exemple de travail proéminent. Cela est généralement fait pour protéger les chaînes qui contiennent des espaces, souvent par rapport aux chaînes de chemin. Les guillemets doubles peuvent être utilisés dans des guillemets simples avec ou sans échappement, mais ils seront interprétés littéralement, c'est-à-dire qu'ils ne conduiront pas à une évaluation. Je vais clarifier ce point dans le post.
AsymLabs