Wie kann man mit `sed` einen exakten String abgleichen? Aber nicht der Teil davon.

8

Ich habe eine Eingabedatei FILE1.TXT wie unten.


11 id1  
12  
13 AGE = 20  
14 NAME = NAME1  
15  
16 id2  
17  
18 AGE = 30  
19 NAME = NAME2  
.  
.  
.  
110 idXYZ  
111  
112 AGE = AGEXYZ  
113 NAME = NAMEXYZ  
114  
115 idZZZ  
116

Ich möchte alle Felder durchsuchen, die zu einer bestimmten ID gehören, und den Wert für NAME erhalten

Ich habe es geschafft, jede ID zu durchlaufen und den folgenden Befehl für jede ID nach Bedarf zu bilden.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'

Das Problem hier ist, ich bekomme die Ausgabe NAME1 , zusätzlich bekomme ich auch NAMEXYZ .

Was sollte geändert werden, damit ich nur NAME1 bekomme, aber nicht NAMEXYZ ?

Um dieses Problem zu umgehen, funktionieren die folgenden Befehle.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'|head -1

Gibt es einen Schalter oder fehlt mir etwas?

Vinay
quelle

Antworten:

3

Wenn Sie die Zeilennummern kennen, nach denen Sie suchen möchten (wie in Ihrem Q angegeben), ziehen Sie die Regex fest, damit Sie nicht mit unerwünschten Zeilen übereinstimmen.

Ändern Sie zum Beispiel:

sed -n '/11/,/14/p' | grep NAME | awk -F "= " '{print $2}'

zu

sed -n '/^11 /,/^14 /p' | grep NAME | awk -F "= " '{print $2}'

Das ^wird mit dem Zeilenanfang übereinstimmen und ein Leerzeichen nach der Nummer garantiert, dass die spezifische Zeilennummer übereinstimmt und Sie keine unerwünschten Blöcke verarbeiten.

Casey
quelle
Das würde helfen. Aber wie kann ich übereinstimmen ^(random no of spaces)11?
Vinay
1
@ VinayChalluru verwendensed -n '/^\s*11 /,/^\s*14 /p'
Casey
1
Es kann eine kurze Hand sein, sed -n '/^11 /,/^14 /p' | awk '/NAME/{print $NF}' wenn Sie dies versucht haben.
Rahul Patil
@ RahulPatil Ja, es funktioniert.
Vinay
5

Verwenden Sie Wortgrenzen:

grep '\bNAME1\b'

würde passen NAME1und nicht NAME1XYZoder XYZNAME1.

Ähnlich,

sed -n '/11\b/,/14\b/p'

würde nicht mit Zeilen übereinstimmen, die 111und enthalten 142.


BEARBEITEN: Es scheint, dass die Zahlen in der Eingabedatei tatsächlich Zeilennummern sind. Wenn das der Fall ist, könnte man einfach sagen:

sed '11,14!d'

um die gewünschten Zeilen zu erhalten.

devnull
quelle
Es gibt nur eine NAMEzwischen den Zeilen 11 und 14. Warum wird also sedauf 111und geschaut 114? Wie kann man es nicht zwischen 111und aussehen lassen 114?
Vinay
@VinayChalluru In der obigen Antwort erfahren Sie, wie Sie den sedAusdruck ändern können .
devnull
Dies beantwortet meine Frage, denke ich. Lass mich versuchen und dich wissen lassen.
Vinay
für Wortgrenzen grepmit -wFlagge? ist es nicht?
Rahul Patil
1
@ RahulPatil Yup, für das obige Beispiel -wwäre äquivalent. Zum sedBeispiel -wist etwas anders.
devnull
4

Sie können AWK verwenden

awk 'NR>=13 && NR<=17 && /NAME/{print $NF}' infile

Dies sieht Zeilen zwischen 13 und 17 aus und sucht dann nach Name. Wenn eine Übereinstimmung vorliegt, wird das letzte Wort von gedruckt Name = LastWord

Rahul Patil
quelle
Wenn ich dies versuche, erhalte ich eine Fehlermeldung, dass die Eingabezeilennummer kleiner als 199 sein muss.
Vinay
@ VinayChalluru können Sie mir Ausgabe mit Befehl zeigen, verwenden Sie paste.ubuntu.com
Rahul Patil
Entschuldigung. Ich habe ein $vorher hinzugefügt NRund das hat den Fehler verursacht.
Vinay
@ VinayChalluru Es ist in Ordnung. Das ist gut, du hast jedes Ans ausprobiert / getestet und etwas Neues gelernt ..: D
Rahul Patil
Genau. Es liegt noch viel mehr vor uns. :-)
Vinay
4

Sie brauchen dafür kein anderes Werkzeug, es sedwird problemlos vollständig gehandhabt.

sed -nr '/11/,/14/{s/^.*NAME =\s*(\S*).*$/\1/p}' <$infile

Dies sollte Ihnen nur die erste Folge von Nicht-Leerzeichen nach der Phrase "NAME =" für jede Zeile liefern, in der diese Phrase zwischen den Zeilen 11 und 14 einer Eingabedatei sedeingespeist wird.

mikeserv
quelle
3

sed ist nicht das richtige Werkzeug für diesen Job. Verwenden Sie awk, wo Sie die gesuchte ID angeben und den nächsten angezeigten NAME drucken können.

awk -v id="id2" '
    $NF == id {have_id = 1} 
    have_id && $0 ~ /NAME/ {print $NF; exit}
' filename
Glenn Jackman
quelle
Können Sie die Zeilen zwei und drei Ihres awk-Befehls erklären?
Erik
0

Generische Version basiert nicht auf Zeilennummer, sondern auf ID-Referenz

sed -n '1h;1!H;
$ {
  x
  s/.*/&\^J/
: clean
#  put your ID pattern here in place of id9
  s/.*\(id9 *\n.*\)id[0-9]\{1,\} *\n.*/\1/
  t clean
  s/.*NAME = \([^[:cntrl:]]*\)\n.*/\1/
  p
  }' YourFile
  1. Laden Sie die gesamte Datei
  2. sauberer Abschnitt nicht Teil der ID-Gruppe (rekursiv)
  3. Nehmen Sie einfach den NAME-Inhaltswert in der Gruppe
  4. Drucken Sie das Ergebnis
NeronLeVelu
quelle
0

Sie können die Zeilen, die übereinstimmende Muster enthalten, mit sed wie folgt drucken:

sed -n '/pattern/p'  Filename
  • -n- Diese Optionen deaktivieren diesen automatischen Druck und sed erzeugt nur dann eine Ausgabe, wenn dies ausdrücklich über den pBefehl angegeben wird.

  • p - drucken

user182845
quelle