Come usare [\ w] + nell'espressione regolare in sed?


24

Sono su Windows, ma suppongo che la mia domanda sia ancora correttamente collocata qui.

C:\Users\User>grep --version
GNU grep 2.6.3

C:\Users\User>sed --version
GNU sed version 4.2.1

Ho notato che i seguenti lavori (in uscita here):

echo here | grep -E "\w+"
echo here | grep -E "[her]+"

Ma questo non funziona (non produce nulla):

echo here | grep -E "[\w]+"

Questo fa di nuovo (in uscita here):

echo here | grep -P "[\w]+"

Quindi [\w]è qualcosa di specifico per le espressioni regolari del Perl, suppongo. È corretto?

Quindi parliamo sed. Funziona (in uscita gone):

echo here | sed -r "s/\w+/gone/"
echo here | sed -r "s/[her]+/gone/"

E ancora, questo non (in uscita here):

echo here | sed -r "s/[\w]+/gone/"

Ora, come posso attivare le espressioni regolari Perl per sed - c'è qualche modo?

Risposte:


11

Diversi strumenti e relative versioni supportano diverse varianti di espressioni regolari. La documentazione di ciascuno ti dirà cosa supportano.

Esistono degli standard in modo da poter contare su un set minimo di funzionalità disponibili in tutte le applicazioni conformi.

Ad esempio, tutte le implementazioni moderne di sede grepimplementano espressioni regolari di base come specificato da POSIX (almeno una versione o l'altra dello standard, ma tale standard non si è evoluto molto in questo senso negli ultimi decenni).

In POSIX BRE ed ERE, hai la [:alnum:]classe di caratteri. Che corrisponde a lettere e cifre nella tua locale (nota che spesso include molto più che a a-zA-Z0-9meno che la locale non sia C).

Così:

grep -x '[[:alnum:]_]\{1,\}'

corrisponde a uno o più allarmi o _.

[\w]è richiesto da POSIX per corrispondere a barra rovesciata o w. Quindi non troverai un grepo sedimplementazione dove è disponibile (a meno che tramite opzioni non standard).

Il comportamento da \wsolo non è specificato da POSIX, quindi le implementazioni sono autorizzate a fare ciò che vogliono. GNU l'ha grepaggiunto molto tempo fa.

GNU grepaveva il suo motore regexp, tuttavia ora usa quello di GNU libc (anche se incorpora una sua copia).

Ha lo scopo di abbinare alnum e trattino basso nel tuo locale. Tuttavia, al momento ha un bug in quanto corrisponde solo a caratteri a byte singolo (ad esempio, non é in una localizzazione UTF-8 anche se è chiaramente una lettera e anche se corrisponde a é in tutti i locali in cui é è un singolo personaggio).

Esiste anche un \woperatore regexp in perl regexp e in PCRE. PCRE / perl non sono espressioni regolari POSIX, sono solo un'altra cosa.

Ora, con il modo in cui GNU grep -Pusa PCRE, ha lo stesso problema di senza -P. Può essere aggirato lì dappertutto usando (*UCP)(sebbene ciò abbia anche effetti collaterali in locali non UTF8).

GNU sedusa anche i regex di GNU libc per i propri regexps. Lo usa in modo tale che non abbia lo stesso bug di GNU grep.

GNU sednon supporta i PCRE. Ci sono alcune prove nel codice che è stato tentato prima, ma non sembra più essere all'ordine del giorno.

Se vuoi le espressioni regolari di Perl, usa perlcomunque.

Altrimenti, direi che invece di provare a fare affidamento su una falsa funzionalità non standard della tua specifica implementazione di sed/ grep, sarebbe meglio attenersi allo standard e utilizzare [_[:alnum:]].


[_[:alnum:]]è una bella soluzione che mi permette di estenderlo come [\w/]( [_[:alnum:]/]in quel caso).
bers

1
Questa risposta è ora superata per quanto riguarda i limiti di GNU grep.
Stéphane Chazelas,

7

Hai ragione - \wfa parte di PCRE - perl espressioni regolari compatibili. Tuttavia, non fa parte della regex "standard". http://www.regular-expressions.info/posix.html

Alcune versioni sedpotrebbero supportarlo, ma suggerirei che il modo più semplice è quello di utilizzare solo perlin sedmodalità specificando il -pflag. (Insieme a -e). (Maggiori dettagli in perlrun)

Ma non hai bisogno di []aggirarlo in questo esempio - è per gruppi di cose valide.

echo here  | perl -pe 's/\w+/gone/'

O su Windows:

C:\>echo here  | perl -pe "s/\w+/gone/"
gone
C:\>echo here  | perl -pe "s/[\w\/]+/gone/"
gone

Vedi perlreper più cose PCRE.

Puoi ottenere il perl qui: http://www.activestate.com/activeperl/downloads


Si prega di notare la differenza tra \we [\w]nella mia domanda. Lo aggiornerò con gli output di ciascun comando per chiarire quale sta funzionando e quale no. In particolare, sedcapisce \w, ma non [\w]. Inoltre, ho bisogno [\w]di lavorare perché voglio usare [\w/]ad esempio.
bers

Nel qual caso, probabilmente è un problema di quotazione. Ad ogni modo, perlpuoi farlo :).
Sobrique,

Grazie! La risposta di Stéphane Chazelas è un po 'più vicina a ciò che ho chiesto (dal momento che non ho installato il perl - un utente Windows du * b, immagino), quindi ho accettato la sua risposta.
bers

Va bene, ma consiglierei di installare Perl su Windows. È una delle prime cose che mi succedono e la trovo estremamente utile.
Sobrique,

\wera in GNU grep (negli anni '80) prima di essere in perl e in GNU emacs probabilmente anche prima.
Stéphane Chazelas,

1

Lo sospetto grepe sto seddecidendo diversamente quando applicare il []e quando espandere il \w. In perl regex \wsignifica qualsiasi carattere di parola e []definisce un gruppo per applicare uno qualsiasi dei personaggi all'interno come una corrispondenza. Se si "espande" il \wprima []sarà una classe di caratteri di tutti i caratteri di parole. Se invece lo fai per []primo, avrai una classe di caratteri con due caratteri \e wquindi corrisponderebbe a qualsiasi modello contenente uno o più di quei due caratteri.

Quindi sembra che sedvedere []e trattarlo come contenente i caratteri esatti da abbinare invece di onorare la sequenza speciale \wcome perle grepfaccia. Ovviamente, []in questo esempio sono del tutto superflui, ma forse si potrebbero immaginare casi in cui sarebbe importante, ma poi si potrebbe farlo funzionare con le parentesi.


Sarei sorpreso se fosse così. \ è un codice di escape e lo useresti per sfuggire ai delimitatori. Inerentemente ciò significa che deve avere una precedenza più elevata di qualsiasi altra cosa. Penso che sia più probabile che non sia implementato perché \wnon fa parte delle specifiche delle espressioni regolari
Sobrique,

Bene, empiricamente sembra essere il caso usando gnu sed per me: mi echo whe\\ere | sed -r 's/[\w]+/gone/ggonehegoneerecome se corrispondesse a ciascuno dei ` and w` e facesse la sostituzione
Eric Renouf

Posso confermare quello che sta vedendo Eric Renouf. Quindi vogliamo in qualche modo liberare la barra rovesciata? :)
bers

Non credo sia la risposta giusta. Sed semplicemente non supporta il mixaggio dei diversi tipi di definizioni delle classi di caratteri, quindi la risposta è se devi usare entrambi i tipi di classi di caratteri per scegliere un altro strumento, o se stai scegliendo sed usa la sintassi che supporta
Eric Renouf,
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.