Ersetzen Sie ein Zeichen aus einer Zeichenfolge, das zwischen der ersten und zweiten Suche liegt, mit sed oder awk

Ersetzen Sie ein Zeichen aus einer Zeichenfolge, das zwischen der ersten und zweiten Suche liegt, mit sed oder awk

Ich muss in einer Datei mit E-Mail-Adressen _(Unterstrich) durch ?(Fragezeichen) ersetzen.

Die Datei sieht wie folgt aus:

EFT_020034-E015133  20140624    /ACC/[email protected]         SHR    END 
EFT_020034-E015133  20140624    /ACC/[email protected]     SHR    END
EFT_020034-E015133  20140624    /ACC/[email protected]        SHR    END

Die erwartete Ausgabe ist:

EFT_020034-E015133  20140624    /ACC/[email protected]         SHR    END 
EFT_020034-E015133  20140624    /ACC/[email protected]     SHR    END
EFT_020034-E015133  20140624    /ACC/[email protected]        SHR    END

Wie kann ich dies insedoderawkohne andere Unterstriche zu beeinflussen und nur den Unterstrich zwischen EMAIL+(constant) und SHR(constant). Der geänderte Inhalt sollte in einer neuen Datei gespeichert werden.

Antwort1

awk macht Folgendes:

$ awk '{ gsub("_", "?", $3) ; print }' < data
EFT_020034-E015133 20140624 /ACC/[email protected] SHR END
EFT_020034-E015133 20140624 /ACC/[email protected] SHR END
EFT_020034-E015133 20140624 /ACC/[email protected] SHR END

Die E-Mail-Adressen befinden sich in Feld 3, daher ersetzen wir nur in Feld 3 _durch ?, auch wenn mehr als eine Adresse vorhanden ist _, mitgsub.

Antwort2

Mit sedIhnen könnten Sie Folgendes tun:

sed -e :1 -e 's/_\([^+]*@\)/?\1/;t1'

Das heißt, ersetzen Sie _, gefolgt von einer Folge von Nicht- +Zeichen, gefolgt von @mit mit ?der Folge von Zeichen, und wiederholen Sie den Vorgang, bis eine Übereinstimmung vorliegt.

Oder um es nur zwischen EMAIL+und zu tun SHR:

sed -e :1 -e 's/\(EMAIL+.*\)_\(.*SHR\)/\1?\2/;t1'

Wenn Sie nur die Zeilen berücksichtigen möchten, die mit beginnen ^EFT, können Sie ein hinzufügen, -e '/^EFT/!b'um diejenigen auszuklammern, die nicht mit beginnen:

sed -e '/^EFT/!b' -e :1 -e 's/\(EMAIL+.*\)_\(.*SHR\)/\1?\2/;t1'

Beachten Sie Folgendes für eine Eingabe wie:

EFT EMAIL+ foo_bar SHR bar_baz EMAIL+ SHR

Beide Unterstriche werden ersetzt, da sie beide zwischen „an“ EMAIL+und „a“ stehen SHR.

Um dies zu vermeiden, können Sie Folgendes tun:

sed '
  /^EFT/!b # leave the non-EFT lines alone (branch out)
  s/%/%p/g; s/</%l/g; s/>/%r/g; # escape the <>% characters with %
  s/EMAIL+/</g; s/SHR/>/g; # replace EMAIL+ and SHR with < and >
  :1
  s/\(<[^<>]*\)_\([^<>]*>\)/\1?\2/; t1
  s/</EMAIL+/g; s/>/SHR/g; # restore EMAIL+ and SHR
  s/%r/>/g; s/%l/</g; s/%p/%/g; # restore the escaped <>%'

Antwort3

sed '/.*EMAIL+\(.*\)SHR.*/{
    h;s//\1/;y/_/?/;G
    s/\(.*\)\n\(.*EMAIL+\).*SHR/\2\1SHR/}'

Dies sollte ziemlich zuverlässig funktionieren. Es ersetzt alles _durch ?zwischen dem letzten EMAIL+Vorkommen in einer Zeile und dem letzten SHRVorkommen in derselben Zeile und nur in den Zeilen, die beide Zeichenfolgen enthalten.

verwandte Informationen