AWK: Verschachtelte bedingte Teilmenge von Zeilen ohne Überschriften

AWK: Verschachtelte bedingte Teilmenge von Zeilen ohne Überschriften

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 keysund Ihre Features in der Datei, featureserhalten 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 ABDerfasst wirdawk

verwandte Informationen