Extrahieren Sie die erste Übereinstimmung in der Zeile mit sed

Extrahieren Sie die erste Übereinstimmung in der Zeile mit sed

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, sedbesteht 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 charvor jedem Match ein , das nicht Teil des Matches ist, und entferne dann alles bis zum letzten charmit dem zweiten sBefehl
    • Eine weitere Option für den zweiten sBefehl besteht darin, alles bis auf ein Zeichen zu entfernen, das nicht Teil der Übereinstimmung ist:
<FILE sed -En '/([[:alpha:]]+-[0-9]+).*/{ s//\1/; s/.*[^[:alnum:]-]//; p; }'

Antwort3

Mit Perlkönnen wir es wie folgt machen:

$ perl -lne 'print /([a-z]+-\d+)/i' file

Ausgabe:

HR-1
HR-2
HR-3
Cov-4

verwandte Informationen