Regex corretto non funzionante in grep


13

Ho questo regex:

(?<=prefix).*$

che restituisce qualsiasi carattere che segue la stringa "prefisso" e funziona perfettamente su qualsiasi motore regex online (ad es. https://regex101.com ). Il problema è quando uso quel regex in bash:

grep '(?<=prefix).*$' <<< prefixSTRING

non corrisponde a nulla. Perché quel regex non funziona con grep?


11
Ciò evidenzia davvero perché regex101 necessita di un selettore di sapore POSIX come per JS, Perl / PHP e Python. Non riesco a contare il numero di volte che ho desiderato.
Jared Smith,


Inoltre, .*$corrisponde a qualsiasi stringa fino alla fine della riga (o fine della stringa), non solo a un singolo carattere.
ilkkachu,

Risposte:


38

Sembra che tu abbia definito la regex giusta, ma non hai impostato i flag sufficienti nella riga di comando per grepcapirlo. Perché per impostazione predefinita grepsupporta BRE e con -Eflag fa ERE. Quello che hai (look-aheads) è disponibile solo nel sapore regex PCRE che è supportato solo in GNU grepcon il suo -Pflag.

Supponendo che sia necessario estrarre solo la stringa corrispondente dopo prefixaver aggiunto un flag aggiuntivo -oper far sapere grepche stampa solo la parte corrispondente come

grep -oP '(?<=prefix).*$' <<< prefixSTRING

Esiste anche una versione grepche supporta le librerie PCRE per impostazione predefinita, pcregrepin cui puoi semplicemente farlo

pcregrep -o '(?<=prefix).*$' <<< prefixSTRING

Spiegazioni dettagliate su vari tipi di regex sono spiegate nella risposta e negli strumenti di questo meraviglioso Giles che implementano ciascuno di essi


38

Le espressioni regolari sono disponibili in molti gusti diversi. Quello che stai mostrando è un'espressione regolare simile al Perl (PCRE, "Espressione regolare compatibile Perl").

grepfa espressioni regolari POSIX. Queste sono espressioni regolari di base (BRE) ed espressioni regolari estese (ERE, se greputilizzato con l' -Eopzione). Consultare il manuale per re_formato regexqualsiasi altro manuale simile a cui grepfa riferimento il manuale sul proprio sistema o i testi POSIX standard a cui ho appena collegato.

Se usi GNU grep, saresti in grado di usare espressioni regolari simili al Perl se lo utilizzassi grepcon l' opzione grepspecifica GNU -P.

Si noti inoltre che greprestituisce le linee per impostazione predefinita, non le sottostringhe dalle linee. Ancora una volta, con GNU grep(e alcune altre grepimplementazioni), è possibile utilizzare l' -oopzione per ottenere solo i bit che corrispondono all'espressione data da ciascuna riga.

Si noti che entrambe -Pe -osono estensioni non standard della specifica POSIX digrep .

Se non si utilizza GNU grep, è possibile utilizzare sedinvece per ottenere il bit tra la stringa prefixe la fine della riga:

sed -n 's/.*prefix\(.*\)/\1/p' file

Quello che fa è stampare solo le linee che sedriescono ad applicare la sostituzione data a. La sostituzione sostituirà l'intera riga che corrisponde all'espressione (che è un BRE), con il pezzo di essa che si verifica dopo la stringa prefix.

Si noti che se prefixsu una riga sono presenti più istanze , la sedvariazione restituirà la stringa dopo l' ultima , mentre la grepvariazione GNU restituirà la stringa dopo la prima (che includerebbe le altre istanze di prefix).

La sedsoluzione sarebbe portatile per tutti i sistemi simili a Unix.


6

Come hanno affermato le altre risposte, grepnon usa un sapore regex con lookbehinds (di default con GNU grep, o per niente con altre versioni).

Se ti ritrovi incapace di usare GNU grepo pcregrep, puoi usarlo perlse ce l'hai.

La riga di comando equivalente perlsarebbe:

perl -ne 'print if /(?<=prefix).*$/' <<< prefixSTRING

Metti la regex desiderata tra le barre. Mentre stai usando Perl, questo usa il sapore regex di Perl .


o print "$&\n" if ...se vogliono produrre solo la parte successiva aprefix
ilkkachu il
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.