Ich habe eine Reihe von Linien gebildet.
Agenda HR-1 Presented by XYZ
HR-2 Debate-1 - All
HR-3 Debate-2 - All
(Cov-4) Conclusion
Jede Zeile hat eine ID des (sed)-Musters [A-Za-z]\+-[0-9]\+
, d. h. auf einen oder mehrere Buchstaben folgt ein Bindestrich (-), gefolgt von einer oder mehreren Zahlen. Sie kommen an beliebiger Stelle in der Zeile vor.
.*
Ich muss die IDs extrahieren. Ich dachte daran , am Anfang und Ende ein anzufügen und auszudrucken \1
, aber ich bekomme es nicht zum Laufen.
DasDie Antwort besagt, dass sed nur die erste Übereinstimmung ersetzt, und das ist richtig:
$ cat /tmp/scratch/x | sed -n 's/\<\([A-Za-z]\+-[0-9]\+\)/ID:\1/p'
Agenda ID:HR-1 Presented by XYZ
ID:HR-2 Debate-1 - All
ID:HR-3 Debate-2 - All
(ID:Cov-4) Conclusion
Aber natürlich .*
würde ein at start gierig zum letzten Match gehen:
$ cat /tmp/scratch/x | sed -n 's/.*\<\([A-Za-z]\+-[0-9]\+\).*/ID:\1/p'
ID:HR-1
ID:Debate-1
ID:Debate-2
ID:Cov-4
Die einzige Möglichkeit, die mir hierfür einfällt, sed
besteht darin, in einem Befehl Markierungen um die ID hinzuzufügen und sie mit einem anderen Befehl wie folgt zu extrahieren.
Gibt es eine bessere Möglichkeit, dies in sed zu tun?
$ cat x | sed -n 's/\<\([A-Za-z]\+-[0-9]\+\)/<id>\1<~id>/;s/.*<id>\(.*\)<~id>.*/\1/;p'
HR-1
HR-2
HR-3
Cov-4
Antwort1
Versuchen Sie mit GNU awk
:
gawk -v FPAT='[A-Za-z]+-[0-9]+' '$1{print $1}' FILE
oder:
gawk -v FPAT='[A-Za-z]+-[0-9]+' '$0=$1' FILE
Antwort2
Versuchen Sie mit sed
:
<FILE sed -En '/([[:alpha:]]+-[0-9]+).*/{ s//:\1/; s/.*://p; }'
- Entfernen Sie alles nach dem gewünschten Match
- Jetzt steht die Übereinstimmung am Ende jeder Zeile – dies kann auf verschiedene Weise gehandhabt werden
- Das Obige ist leicht lesbar – platziere
char
vor jedem Match ein , das nicht Teil des Matches ist, und entferne dann alles bis zum letztenchar
mit dem zweitens
Befehl - Eine weitere Option für den zweiten
s
Befehl besteht darin, alles bis auf ein Zeichen zu entfernen, das nicht Teil der Übereinstimmung ist:
- Das Obige ist leicht lesbar – platziere
<FILE sed -En '/([[:alpha:]]+-[0-9]+).*/{ s//\1/; s/.*[^[:alnum:]-]//; p; }'
Antwort3
Mit Perl
können wir es wie folgt machen:
$ perl -lne 'print /([a-z]+-\d+)/i' file
Ausgabe:
HR-1
HR-2
HR-3
Cov-4