Grep distingue-t-il une variable et le $ regex?

Sep 26 2020

Je veux grep pour une variable qui a la chaîne test, mais je veux aussi m'assurer qu'elle ne trouvera testque si c'est le seul mot sur une ligne.

Alors, j'ai essayé ceci:

string=test
echo "test" | grep "$string$"

Je voudrais savoir si grepsait que la première partie, $string(dans grep " $ string $"), demande de trouver la chaîne test, tandis que la dernière partie, $(dans grep "$ string $ " demande de trouver test, mais rien ne devrait être après testdans la ligne Est grepcapable de distinguer en $stringtant que variable et seulement en $tant que regex pour la fin de la ligne, ou dois-je utiliser une certaine manière de les distinguer?

Réponses

15 Quasímodo Sep 26 2020 at 21:20

Grep ne sait rien qu'il ne voit. Si grep voit $string$, il essaiera de correspondre $string{end-of-line}. Ce qui se passe, c'est que le shell étend la variable $stringavant de se greplancer, de sorte que la fonction grepreçoit test$comme expression régulière.

Mais, étant donné le mot $string$, pourquoi le dernier $n'est pas étendu alors que l' $stringest? Car $n'est pas un nom de variable valide. Ceci est très clair dans la spécification POSIX :

Si le paramètre n'est pas entouré d'accolades et est un nom, le développement doit utiliser le nom valide le plus long (voir Nom XBD ), que la variable représentée par ce nom existe ou non.

Et les états de nom XBD

Dans le langage de commande du shell, mot composé uniquement de traits de soulignement, de chiffres et d'alphabet du jeu de caractères portable. Le premier caractère d'un nom n'est pas un chiffre.

Et il y a aussi des paramètres spéciaux , tels que $$, $@, $#, etc ..

Si vous ne voulez pas vous souvenir de tout cela, suivez simplement les conseils de Gordon Davisson et échappez à tout $ce qui ne devrait pas introduire de variable pour vous assurer qu'elle sera préservée.

$ echo "$string$" test$
$ echo "$string\$" test$
$ echo "\$string\$" $string$

Souvenez-vous également que les variables sont développées entre guillemets doubles mais pas entre guillemets simples.

$ echo 'test' | grep '$string$'   # No match, $string is not expanded $ echo 'test' | grep "$string$"   # Match, $string is expanded
test

Je veux grep pour une variable qui a la chaîne test, mais je veux aussi m'assurer qu'elle ne trouvera testque si c'est le seul mot sur une ligne.

Pour cela, vous avez besoin de l'expression régulière ^test$(pour ancrer la chaîne au début et à la fin de la ligne) ou d'utiliser l' -xindicateur degrep . Votre tentative d'origine correspondrait Atestcar l'expression régulière test$n'est pas ancrée au début de la ligne.

$ echo Atest | grep "$string$"
Atest
$ echo Atest | grep -x "$string"
$ echo Atest | grep "^$string$"