AWK: subconjunto condicional aninhado de linhas sem cabeçalhos

AWK: subconjunto condicional aninhado de linhas sem cabeçalhos

Eu tenho uma pergunta bastante específica e consegui encontrar muitos subconjuntos condicionais usando awk, mas nenhum que forneça código explícito suficiente para generalizar para minha situação. Eu tenho um arquivo 'chaves' e um arquivo 'recursos'sem cabeçalhos. A tabela 'chaves' contém duas variáveis, KEY e GROUP (1ª e segunda colunas, respectivamente), exemplo abaixo.

    1          GROUP0
    2          GROUP0
    3          GROUP1
    4          GROUP1
    5          GROUP2
    6          GROUP2  

O arquivo 'features' contém uma lista de recursos de widgets como este (ID, FEATURE, VALUE 1ª, 2ª e 3ª colunas, respectivamente).

    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

Estou tentando selecionar todas as linhas para um ID que tem um valor de 'KEY' que está na coluna 'KEY' de 'chaves' para uma lista codificada de valores de 'GROUP'. O resultado desejado é

    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

Alguma ideia?

Responder1

Aqui está uma abordagem de 3 passagens com o 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

Supondo que o texto acima esteja salvo em selectrows.awk, use-o assim:

awk -f selectrows.awk keys.txt features.txt features.txt

ou, tudo em uma linha:

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

Responder2

Supondo que você tenha as relações chave/grupo no arquivo keyse seus recursos no arquivo, featuresos resultados abaixo serão esperados de acordo com a entrada fornecida:

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

É apenas uma solução, não necessariamente boa, talvez até a pior em termos de desempenho, mas ainda assim uma.

Responder3

Encontrei esta solução mais curta:

grep -P "^\ +[`awk '$3==""{a[$1]=$2}; $2=="KEY" && $3 in a {printf "%s", $1}' \
<(cat keys features)`]" features

Ele gera um comando parecido com este:

grep -P "^\ +[ABD]" features

... onde a ABDparte do meio é reunida pela awkinstrução

informação relacionada