Come cercare e sostituire più aghi con una parola tramite un'espressione?


8

Supponiamo di avere un file di testo:

foo fnord bar
bizz foo poit

E ora vorrei sostituire sia "foo" che "bar" in "narf".

So che potrei usare:

 sed -e 's/foo/narf/g' -e 's/bar/narf/g' fileName

Tuttavia, vorrei lavorare con un operatore OR che dice alla regex di abbinare entrambi gli aghi tramite un'unica espressione.

Colpendo alcuni manuali suppongo che la pipa dovrebbe adattarsi alle mie esigenze, ma ci ho provato

sed -e 's/foo|bar/narf/g' -i fileName

e non ha funzionato e non sta nemmeno generando un errore.

Cosa sto facendo di sbagliato qui?

Risposte:


10

Utilizzare l' -ropzione per la sintassi regexp estesa:

sed -r -e 's/foo|bar/narf/g'

Altrimenti sfuggire alla disgiunzione come \|:

sed -e 's/foo\|bar/narf/g'

6

Esistono molte variazioni sulla sintassi delle espressioni regolari . I primissimi strumenti nel mondo unix che avevano espressioni regolari non avevano le piene capacità di espressioni regolari, solo set di caratteri ( […]e .), ripetizione ( *) e ancore di linea ( ^e $). Le espressioni regolari di base hanno solo questi operatori. Sed è uno strumento di vecchia scuola e utilizza regexps di base.

Molte implementazioni di sed hanno estensioni per la corrispondenza completa di regexp. Poiché il personaggio |rappresenta se stesso, devi usarlo \|per l'alternanza e in modo simile \(e \)per il raggruppamento. Si noti che lo standard POSIX non \|richiede il supporto supportato nelle espressioni regolari di base e alcuni sistemi (ad esempio OpenBSD ) non lo hanno.

Alcune versioni di sed hanno un'opzione per passare a espressioni regolari estese , dove (…)viene utilizzato per il raggruppamento e |per l'alternanza. Con GNU sed (cioè sotto Linux o Cygwin) o Busybox , passa l' -ropzione. Su FreeBSD o OSX , passa l' -Eopzione.

Se il tuo sed non ha alternanza, puoi chiamare awkinvece. È obbligatorio per POSIX , ma un po 'dettagliato per questa attività e non supporta i riferimenti indietro.

awk '{gsub(/foo|bar/, "narf")}' <fileName.old >fileName.new

A proposito, solo GNU e Busybox possono supportare la sostituzione dei file in atto. Awk e altre versioni di sed no. Vedi Posso fare in modo che `cut` cambi un file sul posto?

Se hai Perl, è spesso utile in un unico modo per elaborare testi con una sola riga. Gran parte di ciò che è facile in sed, awk e il resto non è molto più difficile in Perl, e puoi cavartela imparando un singolo (se complesso) strumento.

perl -i -pe 's/foo|bar/narf/g' fileName

0

Puoi usare Vim in modalità Ex:

ex -sc '%s/\vPA|QU/RO/g|x' file
  1. % seleziona tutte le righe

  2. s sostituto

  3. \v accendi la magia

  4. g sostituzione globale

  5. x salva e chiudi

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.