Ich habe einen String, aus dem ich einen Teilstring extrahieren muss, aber das Ende meines regulären Ausdrucks wird wiederholt. Ich möchte, dass sed bei der ersten Instanz des Endes meines regulären Ausdrucks stoppt, ähnlich wie instr()-Funktionen in vielen Sprachen die erste Instanz zurückgeben. Beispiel:
echo "This is a test some stuff I want string junk string end" | sed -n 's/.*\(.te.*ng\).*/\1/p'
returns: test some stuff I want string junk string
I want to return: test some stuff I want string
Antwort1
grepAnsatz (erfordertPCREUnterstützung):
s="This is a test some stuff I want string junk string end"
grep -Po 'te.*?ng' <<< $s
AlternativeperlAnsatz:
perl -ne 'print "$&\n" if /te.*?ng/' <<< $s
Die Ausgabe (für beide Ansätze):
test some stuff I want string
.*?
-?
hier istnicht geizigModifikator, weist auf Übereinstimmung hin inminimalistische Mode
Antwort2
Gehen Sie dazu in zwei Schritten vor: Entfernen Sie zuerst das Präfix (falls das Abschlusszeichen im Präfix vorhanden war), und entfernen Sie dann alles nach dem Präfix. Verwenden Sie den T
Befehl, um eine Zeile zu überspringen, wenn sie nicht übereinstimmt:
echo "This is a test some stuff I want string junk string end" |
sed -n 's/.*\(.te.*ng\)/\1/; T; s/\(ng\).*/\1/p'
Alternativ können Sie zunächst die nicht übereinstimmenden Zeilen löschen und dann den Ersatz in Ruhe durchführen.
echo "This is a test some stuff I want string junk string end" |
sed '/.*\(.te.*ng\)/!d; s/.*\(.te.*ng\)/\1/; s/\(ng\).*/\1/'
Alternativ führen Sie die Ersetzungen und den endgültigen Ausdruck nur auf übereinstimmenden Zeilen durch.
echo "This is a test some stuff I want string junk string end" |
sed '/.*\(.te.*ng\)/ { s/.*\(.te.*ng\)/\1/; s/\(ng\).*/\1/p; }'
Antwort3
Ich würde in Ihrem Fall vorschlagen, den Cut-Befehl zu verwenden
echo "I am a useful and I am a string. Did I mention that I'm a string?" | cut -d "string" -f1
Das würde den String in drei Teile schneiden (vor dem ersten, nach dem zweiten und zwischen dem 'String'). Mit -d"" können Sie auswählen, welches Muster Sie als Cutter verwenden möchten und mit -fNumber wählen Sie, welcher Teil genommen werden soll. Problem: Der 'String' wird entfernt. Lösung:
String=`echo "I am a useful and I am a string. Did I mention that I'm a string?" | cut -d "string" -f1`
String="$(String) string"
echo $String
Es fügt das entfernte Trennzeichen "string" am Ende der Variable $String hinzu, die mit der Ausgabe definiert wurde
Antwort4
# So führen Sie den Greedy-Match durch: "test .*? string" mit POSIX sed
sed -e '
/test.*string/!d; # non-interesting line
/^test/s/string/&\
/; # append marker after the first substring "string"
/\n/{P;d;} # initial portion of pattern space is our result
s/test/\
&/;D; # remove portion before the substring "test"
' yourfile
Ein andererPOSIX-lyDie Methode besteht darin, die Teilzeichenkette "string" einzeln vom Ende des Musterraums zu entfernen, bis nur noch eine übrig ist (nach der Teilzeichenkette "test"). Dann muss nur noch die Teilzeichenkette "test" in den Vordergrund gebracht werden:
sed -e '
:loop
s/\(test.*string\).*string.*/\1/
tloop
/^test/!s/test/\
&/;/\n/D
' yourfile