Perché '[az] *' corrisponde a stringhe non alfabetiche?


9

Ho un file alphanumcon queste due righe:

123 abc
this is a line

Sono confuso sul perché, quando corro sed 's/[a-z]*/SUB/' alphanum, ottengo il seguente output:

SUB123 abc
SUB is a line

Stavo aspettando:

123 SUB
SUB is a line

Ho trovato una soluzione (usare sed 's/[a-z][a-z]*/SUB/'invece), ma non capisco perché funzioni e il mio no.

Puoi aiutare?



@Kamaraj, quello è simile, ma ha i modelli di shell contro le confusioni di regex in cima (e le risposte si concentrano sul primo, poiché è quello che ls foo*usa lì). Comunque, se trovi domande che sono duplicati, penso che dovresti essere in grado di contrassegnarle come tali.
ilkkachu,

Dai un'occhiata a regexr.com per immagini dal vivo e spiega
RozzA

@RozzA Si noti che il sito Web a cui si collega supporta le espressioni regolari Javascript e Perl, non le espressioni regolari POSIX.
Kusalananda

Risposte:


28

Il modello [a-z]*corrisponde a zero o più caratteri nell'intervallo adi z(i reali caratteri dipendono dalla localizzazione corrente). Ci sono zero di questi caratteri all'inizio della stringa 123 abc(cioè il pattern corrisponde) e anche quattro di loro all'inizio di this is a line.

Se è necessaria almeno una corrispondenza, utilizzare [a-z][a-z]*o [a-z]\{1,\}oppure abilitare espressioni regolari estese con sed -Ee utilizzare [a-z]+.

Per visualizzare la corrispondenza del motivo, aggiungi le parentesi intorno a ogni corrispondenza:

$ sed 's/[a-z]*/(&)/' file
()123 abc
(this) is a line

Oppure, per vedere tutte le partite sulle linee:

$ sed 's/[a-z]*/(&)/g' file
()1()2()3() (abc)
(this) (is) (a) (line)

Confronta l'ultimo risultato con

$ sed -E 's/[a-z]+/(&)/g' file
123 (abc)
(this) (is) (a) (line)

7
[a-z]Abbina tecnicamente gli elementi di confronto che possono essere composti da più di un personaggio. Ad esempio, in alcune località ungheresi, [a-z]partite deldzs
Stéphane Chazelas

12

Perché *corrisponde a zero o più ripetizioni dell'atomo precedente e tutti i motori regex cercano di trovare la prima corrispondenza. C'è una sottostringa di esattamente zero lettere all'inizio della stringa, quindi è lì che corrisponde. Nel caso in cui la stringa inizi con una lettera, ne *corrisponde il maggior numero possibile, ma ciò è secondario nel trovare la corrispondenza più a sinistra.

Le corrispondenze di lunghezza zero possono essere un po 'problematiche e, come hai visto, la soluzione è modificare il modello in modo che richieda almeno un carattere. Con regex estese, potresti farlo +:sed -E 's/[a-z]+/SUB/'

Per divertimento, prova:

echo 'less than 123 words' | sed 's/[0-9]*/x/g'
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.