
Ich habe eine ziemlich spezielle Frage und konnte viel über bedingte Teilmengenbildung mit awk finden, aber nichts, das mir genügend expliziten Code liefert, um ihn auf meine Situation zu verallgemeinern. Ich habe eine Datei „keys“ und eine Datei „features“, beideohne Header. Die Tabelle „Schlüssel“ enthält zwei Variablen, KEY und GROUP (erste bzw. zweite Spalte), siehe Beispiel unten.
1 GROUP0
2 GROUP0
3 GROUP1
4 GROUP1
5 GROUP2
6 GROUP2
Die Datei „Features“ enthält eine Liste mit den Features von Widgets wie folgt (ID, FEATURE, VALUE, 1., 2. und 3. Spalte).
A num_user 10
A KEY 4
B num_user 2
B KEY 2
B battery Large
C num_user 10
C KEY 15
D num_user 2
D KEY 2
D battery Small
E num_user 2
E KEY 7
E battery Small
Ich versuche, alle Zeilen für eine ID auszuwählen, die den Wert „KEY“ hat, der sich in der Spalte „KEY“ von „keys“ für eine fest codierte Liste von „GROUP“-Werten befindet. Das gewünschte Ergebnis ist
A num_user 10
A KEY 4
B num_user 2
B KEY 2
B battery Large
D num_user 2
D KEY 2
D battery Small
Irgendwelche Ideen?
Antwort1
Hier ist ein 3-Pass-Ansatz mit awk:
FNR == 1 {
fn++ # counter for File Number, starts at 1
}
fn == 1 {
key[$1] = 1 # first file: store keys
}
fn == 2 && $2 == "KEY" && $3 in key {
id[$1] = 1 # second file, first pass: store id's
}
fn == 3 && $1 in id # second file, 2nd pass: print rows
Angenommen, das Obige ist in gespeichert selectrows.awk
, verwenden Sie es folgendermaßen:
awk -f selectrows.awk keys.txt features.txt features.txt
oder alles in einer Zeile:
awk 'FNR == 1 {f++}; f == 1 {k[$1]}; f == 2 && $2=="KEY" && $3 in k {i[$1]}; f == 3 && $1 in i' keys.txt features.txt features.txt
Antwort2
Vorausgesetzt, Sie haben die Schlüssel-/Gruppenbeziehungen keys
und Ihre Features in der Datei, features
erhalten Sie gemäß Ihrer Eingabe die folgenden erwarteten Ergebnisse:
awk '{print $2}' keys | sort -u | xargs -i_group awk '{if($2=="_group")print $1}' keys | sort -u | xargs -i_key awk '{if ($3=="_key" && $2=="KEY")print $1}' features | sort -u | xargs -i_id awk '{if($1=="_id")print $0}' features
Es handelt sich lediglich um eine Lösung, nicht unbedingt eine gute, vielleicht sogar die schlechteste in Bezug auf die Leistung, aber immerhin eine.
Antwort3
Ich habe diese kürzere Lösung gefunden:
grep -P "^\ +[`awk '$3==""{a[$1]=$2}; $2=="KEY" && $3 in a {printf "%s", $1}' \
<(cat keys features)`]" features
Es wird ein Befehl generiert, der wie folgt aussieht:
grep -P "^\ +[ABD]" features
...wobei der -Teil in der Mitte durch die Aussage ABD
erfasst wirdawk