Grep distingue una variabile e la $ regex?

Sep 26 2020

Voglio grep per una variabile che ha la stringa test, ma voglio anche assicurarmi che trovi solo testse questa è l'unica parola su una riga.

Quindi, ho provato questo:

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

Vorrei sapere se grepsa che la prima parte, $string(in grep " $ string $"), chiede di trovare per la stringa test, mentre l'ultima parte, $(in grep "$ string $ " chiede di trovare test, ma niente dovrebbe essere dopo testnella riga È in grepgrado di distinguere $stringcome variabile e solo $come regex per la fine della riga, o devo usare un certo modo per distinguerli?

Risposte

15 Quasímodo Sep 26 2020 at 21:20

Grep non sa niente che non vede. Se grep vede $string$, proverà a corrispondere $string{end-of-line}. Quello che succede è che la shell espande la variabile $stringprima che grepentri in azione, in modo che grepriceva test$come regex.

Ma, data la parola $string$, perché l'ultimo $non è espanso mentre lo $stringè? Perché $non è un nome di variabile valido. Questo è molto chiaro nelle specifiche POSIX :

Se il parametro non è racchiuso tra parentesi graffe ed è un nome, l'espansione utilizzerà il nome valido più lungo (vedere Nome XBD ), indipendentemente dal fatto che la variabile rappresentata da quel nome esista o meno.

E gli stati del nome XBD

Nel linguaggio dei comandi della shell, una parola composta esclusivamente da trattini bassi, cifre e alfabetici dal set di caratteri portatile. Il primo carattere di un nome non è una cifra.

E ci sono anche i parametri speciali , come ad esempio $$, $@, $#, ecc ..

Se non vuoi ricordare tutto questo, segui semplicemente il consiglio di Gordon Davisson ed evita ogni cosa $che non dovrebbe introdurre una variabile per assicurarti che venga preservata.

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

Ricorda anche che le variabili vengono espanse tra virgolette doppie ma non tra virgolette singole.

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

Voglio grep per una variabile che ha la stringa test, ma voglio anche assicurarmi che trovi solo testse questa è l'unica parola su una riga.

Per questo, hai bisogno della regex ^test$(per ancorare la stringa sia all'inizio che alla fine della riga) o per usare il -xflag digrep . Il tuo tentativo originale corrisponderebbe Atestperché la regex test$non è ancorata all'inizio della riga.

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