
Die ursprüngliche Zeichenfolge lautet wie folgt:
str-str001-002_01
str-str005-006_05
Ich möchte den String vor der Zahl und nach dem Unterstrich extrahieren, also sähe es folgendermaßen aus:
str-str_01
str-str_05
Ich erinnere mich, dass sed Muster wie folgt in Gruppen aufteilen konnte:
sed -n 's/\(^.*\)\([0-9]-[0-9]\)\(.*$\)/\1\3/p'
aber es druckt:
str-str0002_01
Dann fällt mir ein, dass [0-9] nur eine Zahl ist, also habe ich es mit dem Pluszeichen oder dem Sternchen probiert. Das Ergebnis war leer.
ps: durch die Verwendung
echo 'str-str001-002_01' | sed -n 's/\(^.*\)\([0-9]-[0-9]\)\(.*$\)/\2/p'
Ich sehe, dass es passt 1-0
.
Dann habe ich es versucht mit:
echo 'str-str001-002_01' | sed -n 's/\(^.*\)\([0-9]\+-[0-9]\+\)\(.*$\)/\2/p'
Es blieben die ersten beiden Zahlen übrig und es stimmt nur überein
1-002
also wie bringt man es zusammen001-002
Antwort1
Dies liefert die erforderliche Ausgabe:
sed -nE 's/^([^0-9]*).*_([^_]+)$/\1_\2/p'
Ausgabe aus Ihrem Beispiel
str-str_01
str-str_05
Erläuterung
sed -nE 's/…/…/p'
- Verwenden Sie EREs, drucken Sie keine Zeilen, wenn sie nicht übereinstimmen^
- Anker am Zeilenanfang([^0-9]*)
- ein möglichst langes Muster abgleichen, das mindestens ein Zeichen enthält, das keine Ziffer ist.*_
- so viele Übereinstimmungen wie möglich (auch nichts), gefolgt von "_
"([^_]+)
- Suche nach einem möglichst langen Muster (mindestens ein Zeichen), das kein Unterstrich ist$
- Anker am Ende der Leine\1_\2
- Ersetzen Sie die gesamte Zeile durch die erste(…)
Übereinstimmung, "_
" und die zweite(…)
Übereinstimmung
Der Grund, warum Ihre Versuche nicht wie erwartet funktioniert haben, ist, dass *
(und +
) gierig ist – es verbraucht so viele Zeichen wie möglich, die mit dem vorhergehenden Atom übereinstimmen. Wenn also ein ERE von (.*)([0-9]+)
auf etwas wie angewendet wird abc123
, .*
verbraucht das abc12
, sodass [0-9]+
nur noch mit übereinstimmt 3
. Sie benötigen ein „keine Ziffer" um die erste Übereinstimmung einzuschränken: ([^0-9]*)([0-9]+)
um abc
und zu erhalten 123
.
Antwort2
$ cat file
str-str001-002_01
str-str005-006_05
$ sed 's/[0-9]\{3\}-[0-9]\{3\}//' file
str-str_01
str-str_05
Der Ersetzungsbefehl hier gleicht ab und entfernt, NNN-NNN
wobei es NNN
sich um eine Folge von drei Ziffern handelt.
Passenmindestens einZiffer, verwenden Sie 1,
anstelle von 3
:
$ sed 's/[0-9]\{1,\}-[0-9]\{1,\}//' file
str-str_01
str-str_05
Dies entspricht der Verwendung in einem erweiterten regulären Ausdruck. Die von standardmäßig +
verwendeten regulären Ausdrücke sind „einfache“ reguläre Ausdrücke und würden einem wörtlichen Pluszeichen entsprechen. Die meisten Implementierungen unterstützen auch erweiterte Ausdrücke mit :sed
+
sed
-E
$ sed -E 's/[0-9]+-[0-9]+//' file
str-str_01
str-str_05
Die Verwendung von *
, wie in , würde nicht funktionieren, da dies dem Bindestrich in (der von null Ziffern umgeben ist) [0-9]*-[0-9]*
entsprechen würde .str-str
Wenn Sie das Gefühl haben, dass Sie wirklich die ganze Zeile abgleichen und die Bits erfassen müssen, die Sie behalten möchten, können Sie dies auch tun. Der folgende Befehl erfasst die anfänglichen Nicht-Ziffern und das letzte Bit, einschließlich des Unterstrichs:
$ sed 's/\([^0-9]*\).*\(_.*\)/\1\2/' file
str-str_01
str-str_05
Dies ist meiner Meinung nach jedoch etwas schwierig zu entziffern und macht Annahmen über den Anfang und das Ende der Zeichenfolge, die Sie in der Frage nie erwähnt haben. Der Anfang kann beispielsweise keine Ziffern vor den Ziffern enthalten, die Sie entfernen möchten, und das Ende der Zeichenfolge wird an derzuletztUnterstrich, nicht unbedingt nach den Ziffern, die Sie entfernen möchten, wenn in diesem Teil der Zeichenfolge mehrere Unterstriche vorhanden sind.
Sie könnten diesen Ausdruck jederzeit um weitere Elemente ergänzen, um sicherzustellen, dass nur das NNN-NNN
Bit nicht erfasst wird. Dadurch würde es jedoch noch schwieriger, den Ausdruck zu verstehen.