EINGANG
AA XXX Y1Y ZZZ GG dhz
rr (AAAa) XXX Y2Y ZZZ TT GGGG UU
AUSGABE
Y1Y
Y2Y
Die Eingabezeilen können variieren. Nur XXX vor Y1Y und ZZZ nach Y1Y sind konstant (sie sind so die Nachbarn von XXX und ZZZ). Y1Y kann alles sein, z. B.: Y1Y, Y2Y, Y1T usw.
Q:wie kann ich die AUSGABE mit awk oder sed oder grep erhalten? (oder gibt es dafür bessere Tools?)
AKTUALISIEREN(Problem): Warum funktioniert es nicht, wenn im Y1Y ein „.“ steht?
[user@notebook ~] echo 'XXX Y1Y ZZZ' | grep -Po "(?<=XXX )(\w+)(?= ZZZ)"
Y1Y
[user@notebook ~] echo 'XXX Y1.Y ZZZ' | grep -Po "(?<=XXX )(\w+)(?= ZZZ)"
[user@notebook ~]
Antwort1
Sie können grep
hierfür die bereitgestellte PCRE-Funktion verwenden:
$ grep -Po "(?<=XXX )\S+(?= ZZZ)" data.txt
Y1Y
Y2Y
Einzelheiten
Diese Lösung nutzt die Lookbehind- und Lookahead-Funktion von PCRE, die Zeichenfolgen mit fester Länge abgleichen kann.
Oben wird hinter jedem nachgeschaut, \w+
ob es ist, XXX
und vor jedem, \w+
um zu sehen, ob es ist ZZZ
. Wenn ja, dann ist es eine Übereinstimmung. Der -o
Schalter auf grep
weist an, nur die Übereinstimmungen zu drucken, d. h \w+
. .
Folgefrage: Können Sie es mit sed machen?
Ich glaube nicht, dass sich dieses Problem mit lösen lässt sed
. Meiner Ansicht nach gibt es zwei Ansätze.
- Speichern Sie mögliche Übereinstimmungen in einer Nebenvariable. Wenn Sie auf ZZZ stoßen, drucken Sie sie aus.
- s/XXX ..unsere Zeichenfolge.. ZZZ/ ..unsere Zeichenfolge../
Nr. 1 scheint ziemlich viel Arbeit zu sein, deshalb werde ich es erst gar nicht versuchen. Hier ist, was bei Ansatz Nr. 2 passiert.
$ sed 's/.*XXX \(.*\) ZZZ.*/\1/' data.txt
Y1Y
Y2Y
AAAa YXX Y2Y ZZZ TT GGGG UU
Es findet also problemlos Übereinstimmungen, tut aber nichts für Zeilen, die nicht übereinstimmen. Es könnte eine Möglichkeit geben, sed
das Löschen dieser Zeilen anzuweisen. In diesem Fall wäre dies eine alternative Lösung.