Grep/Awk/Sed für eine Reihe von Zeilen von "0010|" bis "0070|" UND die eine Übereinstimmung in $PH_NO enthält
Unten sind die Beispieldaten. Ich muss nach der Telefonnummer suchen, die im Feld 0012 vorhanden ist, und nach den entsprechenden vollständigen Kundendatensätzen, Zeilen von 0010 bis 0070. Eine Datendatei kann zwei oder drei Kundendatensätze mit derselben Telefonnummer enthalten und ich muss sie alle abrufen.
0010|Kumar||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 222| PH Number
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|
0010|RAM||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 333| PH Number
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|
0010|Joe||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 222| PH Number
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|
Hinweis: Ich bin auf einem AIX-Server mit ksh.
Antwort1
Sie möchten also den gesamten Datensatz von 0010 bis 0070, sofern die PH-Nummer übereinstimmt ? Dann funktioniert $PH_NO"
dieser Einzeiler:sed
sed "/^0010/,/^0070/H;/^0010/h;/^0070/! d;x;/|$PH_NO| PH Number/! d"
/^0010/,/^0070/H
um einen Datensatz von 0010 bis 0070 an den Haltebereich anzuhängen/^0010/h
die 0010 soll nicht angehängt werden, sondern einen neuen Datensatz beginnen, also kopiere sie in den Hold Space/^0070/! d
keine weitere Verarbeitung oder Ausgabe, es sei denn, es handelt sich um das Element 0070x;/|$PH_NO| PH Number/! d"
Tauschen Sie die Leerzeichen aus, sodass sich der gesamte Datensatz nun im Musterbereich befindet, und löschen Sie ihn, wenn er die besagte Nummer nicht enthält.
Antwort2
for r in `grep -n '^0010\|^0012\|^0070' CUSTOMER_FILE | grep -C1 '[0-9]\+:0012|149 196 222|' | grep -o '^[0-9]\+' | paste -d, - - - | sed 's/,[0-9]\+,/,/g'`; do sed -n "$r"p CUSTOMER_FILE; echo; done
149 196 222
im obigen Befehl ist die Telefonnummer des Kunden. Ändern Sie sie in die Telefonnummer, die Sie herausfinden möchten.
CUSTOMER_FILE
ist die Datei, nach der Sie suchen möchten. Ändern Sie sie in Ihren Dateinamen.
Sie können den Code auch in ein Bash-Skript einfügen und 149 196 222
durch $1
und durch ersetzen CUSTOMER_FILE
. $2
Sagen wir find-customer.sh, dann können Sie das Skript wie folgt ausführen
./find-customer.sh '149 196 222' your-file-name
Voraussetzung dieses Codestücks:
- Bash, GNU-Umgebung (GNU grep, GNU sed)
- Ihre Datei muss dem unten stehenden Format entsprechen
0010 ... <no 0010 or 0012 or 0070> ... 0012 ... <no 0010 or 0012 or 0070> ... 0070 ... <repeated content as above or end of file>
AKTUALISIEREN
Dies ist eine Hochleistungsversion. (Zumindest höher als die oben genannte Originalversion. Es ist überhaupt keine For-Schleife beteiligt.)
grep -n '^0010\|^0012\|^0070' CUSTOMER_FILE | grep -C1 '[0-9]\+:0012|149 196 222|' | grep -o '^[0-9]\+' | paste -d, - - - | sed -r 's|([0-9]+),[0-9]+,([0-9]+)|\1,\2p;\2a|g' | sed -n -f - CUSTOMER_FILE
UPDATE für AIX
Da der Fragesteller unter AIX arbeitet, unterstützt das Grep unter AIX die Kontextoptionen -A, -B und -C nicht.
Im Internet gibt es eine Vielzahl von "cgrep" (context grep)-Implementierungen, um dieses Problem zu lösen (um die GNU grep-Kontextoption zu simulieren). Die meisten davon können jedoch nicht dieselbe Ausgabe wie GNU grep liefern. Nur eine, die ich gefunden habe, kommt der GNU grep-Kontextoption am nächsten. Der Link isthttps://stackoverflow.com/questions/1685678/advanced-grep-unix/1685782#1685782
Ich habe für diesen Fall einige notwendige Änderungen vorgenommen.
#!/bin/bash
BEFORE=$1
AFTER=$1
FILE=/tmp/.cattmp
PATTERN="$2"
cat > $FILE
for i in $(grep -n "$PATTERN" $FILE | sed -e 's/\:.*//')
do head -n $(($AFTER+$i)) $FILE | tail -n $(($AFTER+$BEFORE+1))
done
rm $FILE
Speichern Sie diese Datei unter grep-context.sh
und ersetzen Sie sie grep -C1
durch ./grep-context.sh 1
meinen obigen Befehl.
Eine andere Möglichkeit, die meiner Meinung nach ein für alle Mal funktioniert, besteht darin, GNU grep unter AIX zu kompilieren. (Kompilieren Sie zur Sicherheit auch GNU sed.)
Antwort3
Sie können dieses Skript verwenden:
#!/bin/sh
read START
read END
read MATCH
REND=$(grep -n "$END" lines | tail -1 | cut -d":" -f 1)
RSTART=$(grep -n "$START" lines | head -1 | cut -d":" -f 1)
sed $RSTART,$REND!d lines | grep "$MATCH"
Legen Sie es in eine Datei und fügen Sie mit diesem Befehl die Ausführungsberechtigung hinzu
chmod +x script.sh
START-Variable:Ihre Startnummern (zB 0010)
END-Variable:Ihre Endvariable (zB 0070)
MATCH-Variable:Das gesuchte Wort/Zeichen/die gesuchte Zahl in einer Zeile (zB 0012)
RSTART-Variable:Die Nummer der Startzeile in der Textdatei (z. B. 1)
REND-Variable:Die Nummer der Startzeile in der Textdatei (z. B. 32)
BEARBEITEN:
Sie können auch sehen, wie oft eine Zeile wiederholt wird, indem Sie die letzte Zeile wie folgt ändern:
sed $RSTART,$REND!d lines | grep "$MATCH" | sort | uniq -c