Subconjunto do conteúdo de um arquivo com base no valor em uma coluna

4

Eu tenho um arquivo de texto como (por exemplo):

apple   V$NFY_Q6_rc V=0.741
apple   V$HOXA7_01_rc   V=0.454
apple   V$ALPHACP1_01_rc    V=0.695
orange  V$SP4_Q5    V=0.747
grapes  V$SP1_Q2_01 V=0.677
grapes  V$SP1_Q6_01_rc  V=0.685
grapes  V$SP1_Q6_rc V=0.884

Eu quero extrair as linhas que têm o maior valor de V (na coluna 3) para cada fruta. Minha saída deve se parecer com:

apple   V$NFY_Q6_rc V=0.741
orange  V$SP4_Q5    V=0.747
grapes  V$SP1_Q6_rc V=0.884

Eu tenho vários arquivos como este em subdiretórios diferentes.

Após o subconjunto, eu usaria o seguinte código para obter o número de ocorrências de uma string específica na coluna 2.

        perl -lanE '$str=$F[1];  $f="/home/$str/list/$str.txt"; $c='grep -c "$str" "$f"';chomp($c);$x=0;$x++ if $c;say "$str\t$x\t$c"' file2

isso resultaria na seguinte saída. Vamos supor que estou procurando a string "SP4" na coluna 2 deste arquivo:

         X       X in file?  number of times it occurs
        NFA            0                            0
        SP4            1                            2
        NFATC1         0                            0

Eu quero o valor V (de cima para ser incluído junto com esta tabela)

          X       X in file?  number of times it occurs      V value
        NFA            0                            0
        SP4            1                            2         0.747
        NFATC1         0                            0

P.S .: Para mais detalhes sobre o programa perl no meio, por favor consulte este link:

         http://stackoverflow.com/questions/23109490/search-for-occurrence-of-a-string-in-another-file-in-a-particular-column
    
por biobudhan 28.04.2014 / 08:53

3 respostas

4

Se a ordem não for importante, duas passagens de sort devem fazer o truque. Na primeira passagem, classifique por campo 1 seguido de classificação inversa pela parte numérica do campo 3 (posição inicial 4). O modificador -b faz com que espaços em branco principais sejam ignorados. Pipe isto para um segundo sort que retorna um registro para cada valor único no campo 1, mas desta vez especifique o modificador de classificação estável ( -s ) para assegurar que o registro com o valor mais alto no campo 3 (que tinha borbulhado para o topo de cada valor no campo 1, cortesia da classificação anterior) é retornado

sort -k1,1 -k3.4b,3nr file.txt | sort -k1,1 -s -u
apple   V$NFY_Q6_rc V=0.741
grapes  V$SP1_Q6_rc V=0.884
orange  V$SP4_Q5    V=0.747
    
por 28.04.2014 / 23:16
2

com awk :

awk -F'[ =]' '$NF>a[$1]{a[$1]=$NF;b[$1]=$0}END{for (i in b) print b[i]}' filename.txt

Isso funciona criando uma matriz a dos valores V, indexada pela primeira coluna. Para cada linha, o valor V é comparado com o valor atual da matriz para aquele índice, e se for maior, então o valor na matriz é atualizado e a linha inteira é armazenada em uma segunda matriz b. Depois que todo o arquivo for processado, tudo em b será impresso.

Exemplo de saída:

orange  V$SP4_Q5    V=0.747
apple   V$NFY_Q6_rc V=0.741
grapes  V$SP1_Q6_rc V=0.884

Se a ordem for importante, você pode canalizar para sort (por exemplo, classificar pelo número V):

awk -F'[ =]' '$NF>a[$1]{a[$1]=$NF;b[$1]=$0}END{for (i in b) print b[i]}' filename.txt | sort -t= -nk2

Dá:

apple   V$NFY_Q6_rc V=0.741
orange  V$SP4_Q5    V=0.747
grapes  V$SP1_Q6_rc V=0.884

Exemplo de trabalho: link

    
por 28.04.2014 / 11:19
0

Aqui está uma solução em perl :

$ perl -F'\s+|=' -anle '
    $h{$F[0]} = [$F[-1],$_] if $F[-1] > $h{$F[0]}->[0];
    END {print $h{$_}->[1] for keys %h}' file
grapes  V$SP1_Q6_rc V=0.884
apple   V$NFY_Q6_rc V=0.741
orange  V$SP4_Q5    V=0.747

Atualizar

Suponha que você tenha dois resultados depois de executar dois one-liner.

file1 :

apple   V$NFY_Q6_rc V=0.741
orange  V$SP4_Q5    V=0.747
grapes  V$SP1_Q6_rc V=0.884

file2 :

X       X in file?  number of times it occurs
NFA            0                            0
SP4            1                            2
NFATC1         0                            0

Você pode tentar isso:

$ awk -F'[ =]+' 'FNR==NR{a[$2]=$NF;next}
            FNR==1{print $0"\tV value";next}
            {for(i in a){
                if(index(i,$1)){
                    print $0"\t"a[i];
                    next;
                }
            }
            print;
        }' file1 file2
X       X in file?  number of times it occurs   V value
NFA            0                            0
SP4            1                            2   0.747
NFATC1         0                            0
    
por 29.04.2014 / 15:39