Quelle est la difference entre grep apple file
et 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).
Quelle est la difference entre grep apple file
et 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).
Réponses:
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 apple
ne contient pas de tels caractères.
Mais considérons un autre exemple: grep apple tree file
recherchera le mot apple
dans les fichiers tree
et file
, tandis que grep "apple tree" file
recherchera le mot apple tree
dans 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 file
produirait 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.
"
) 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 USER
contient (par exemple johnstacen
).
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.
grep a*b equations.txt
il rechercheraa*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 commefind . -name *.txt
entraî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.