2016-05-27 3 views
3

Ich bin ein bisschen ein Anfänger, Shell-Scripting und awk. Könnte jemand eine effizientere und elegantere Lösung für das, was ich unten mache, vorschlagen, um eine Schlüsselsuche zwischen zwei Dateien durchzuführen?Wie führe ich eine Schlüsselfeldsuche in einer Datei mit bash oder awk aus?

zwei Eingabedateien:

Datei 1 - Enthält eine einzelne Spalte Schlüsselfeld (Server-ID Mess Minuten):

key_column 
server026-AckDelayAverage-00:01:00 
server026-AckDelayMax-00:01:00 
server026-AckSent-00:01:00 
server026-DigEnvValidationLatestTime-00:01:00 
server026-DigEnvValidationTimeAverage-00:01:00 

File 2 - Comma das Tastenfeld und die Anzahl der anderen Felder enthält, abgetrennt

key_column,host,date,minute,metricname, metric value 
server026-AckDelayAverage-00:01:00,server026,May 24 2016,00:01:00,AckDelayAverage,942 
server026-AckDelayMax-00:01:00,server026,May 24 2016,00:01:00,AckDelayMax,5855 
server026-AckSent-00:01:00,server026,May 24 2016,00:01:00,AckSent,49038 

Meine Logik ist:

Loop through file1 
If key found in File2 
    print file1.key , file2.field3 , file2.field6 to file3 
else 
    print file1.key + 'KEY_NOT_FOUND' text to file3 
fi  

Also sollte die Datei3-Ausgabe eine Zeile für jeden Datensatz in Datei1 haben.

Der folgende Code scheint zu funktionieren, aber könnte jemand eine effizientere und elegantere Methode vorschlagen, dies zu erreichen?

while read key ; 
do 
     metric_found=`grep $key file2` 
    if [[ ! -z $metric_found ]] 
    then 
      echo ${metric_found} | awk -F "," '{print $1",$3,"$6}' 
    else 
      echo ${key},KEY_NOT_FOUND 
    fi 
done < file1 

Beispiel Ausgabe von bestehenden Skript auf der Grundlage der Beispieldaten:

server026-AckDelayAverage-00:01:00,May 24 2016,942 
server026-AckDelayMax-00:01:00,May 24 2016,5855 
server026-AckSent-00:01:00,May 24 2016,49038 
server026-DigEnvValidationLatestTime-23:59:00,KEY_NOT_FOUND 
server026-DigEnvValidationTimeAverage-23:59:00,KEY_NOT_FOUND 

Dank ..

+1

Wenn Sie gerade suchen Allgemeine Kommentare und Verbesserungen, Ihre Frage könnte besser sein geeignet für die Code-Review-Website – Matt

+0

Bitte lesen Sie [Warum-verwendet-eine-Shell-Schleife-zu-Prozess-Text-in Betracht gezogen-Bad-Praxis] (http://unix.stackexchange.com/questions/169716/why -ist-Verwenden-einer-Shell-Schleife-zu-Prozess-Text-betrachtet-schlecht-Übung), um einige der Gründe zu verstehen, warum Sie awk dafür verwenden sollten, nicht eine Shell-Schleife. –

+1

Vielen Dank für den Artikel. Sehr informativ. Ich werde von nun an awk für diese Art der Verarbeitung verwenden. – JustinE

Antwort

3

versuchen Sie dies:

awk 'BEGIN{FS=OFS=","}NR==FNR{a[$1]=1;b[$1]=$3;c[$1]=$6;}NR>FNR{if (a[$1]) print $1,b[$1],c[$1]; else print $1,"KEY_NOT_FOUND";}' file2 file1 > file3 
+0

danke, für mein Verständnis könnten Sie eine Erklärung geben, wie das funktioniert? – JustinE

2
$ cat tst.awk 
BEGIN { FS=OFS="," } 
NR==FNR { file2[$1] = $3 OFS $6; next } 
FNR>1 { print $1, ($1 in file2 ? file2[$1] : "KEY_NOT_FOUND") } 

$ awk -f tst.awk file2 file1 
server026-AckDelayAverage-00:01:00,May 24 2016,942 
server026-AckDelayMax-00:01:00,May 24 2016,5855 
server026-AckSent-00:01:00,May 24 2016,49038 
server026-DigEnvValidationLatestTime-00:01:00,KEY_NOT_FOUND 
server026-DigEnvValidationTimeAverage-00:01:00,KEY_NOT_FOUND 
+0

danke. Könntest du mir zum Verständnis die Zeilen 2 und 3 erklären? – JustinE

+1

'NR == FNR' gilt nur für die erste Datei, so dass Zeile 2 ein assoziatives Array auffüllt, das jeden der ersten Feldwerte von Datei1 dem 2. und 3. Feld derselben Zeile zuordnet. Zeile 3 druckt nur den Inhalt des Arrays file1, der durch das erste Feld in Datei2 indiziert wird, wenn vorhanden, unter Verwendung eines ternären Ausdrucks. Ich empfehle das Buch Effective Awk Programming, 4. Auflage, von Arnold Robbins. –

Verwandte Themen