Aplique se condição a todas as linhas de um arquivo delimitado por tabulação que tenham o mesmo valor em uma coluna específica:

0

Basicamente eu quero aplicar se a condição nas linhas que têm o mesmo valor na coluna2. No exemplo, as primeiras três linhas têm o mesmo valor na coluna2 (Disease1). Agora, para essas três linhas, desejo aplicar a condição IF - se a terceira coluna for 'Alta', escreva somente essa linha para o arquivo de saída. Se a terceira coluna não tiver 'Alta', procure 'Média' e imprima-a. Se 'Medium' também não estiver lá, imprima a linha contendo o valor 'Low'.

Entrada:

id1 Disease1 High
id2 Disease1 Medium
id3 Disease1 Low
id4 Disease2 Low
id5 Disease3 Medium
id6 Disease3 Low

Resultado esperado:

id1 Disease1 High
id4 Disease2 Low
id5 Disease3 Medium
    
por LiNi 21.09.2018 / 13:08

4 respostas

2
awk 'BEGIN { FS=OFS="\t"; d["High"]=1; d["Medium"]=2; d["Low"]=3 } { print d[$3], $0 }' file |
sort -t $'\t' -k3,3 -k1,1n | sort -t $'\t' -s -u -k3,3 | cut -f 2-

Infelizmente, as palavras "Alta", "Média" e "Baixa" não são ordenadas alfabeticamente nesta ordem, então, ao invés disso, prefixamos cada linha com os inteiros 1, 2 e 3 para as palavras correspondentes na coluna 3. feito com o script awk . O inteiro é separado do conteúdo original por um caractere de tabulação e indica a gravidade da doença (1 é o mais alto).

Em seguida, classificamos os dados modificados sobre a doença e neste campo inteiro, para que os registros sejam agrupados por doença e ordenados por gravidade.

Em seguida, fazemos uma "classificação única" com apenas as doenças como chave (o segundo sort ). Isso elimina qualquer doença duplicada e, para cada doença, ficamos apenas com o registro mais grave. O -s faz com que sort use um algoritmo de classificação estável que preserva o reordenamento de registros com chaves idênticas.

O cut no final remove o número inteiro que adicionamos anteriormente com awk .

O pipeline pressupõe o uso de bash para especificar o delimitador de campo para os comandos sort . Se bash não for usado, insira uma única tab literal ao invés de usar $'\t' (você pode fazer isso pressionando Ctrl + V Tab ).

    
por 21.09.2018 / 13:37
1

Se as prioridades forem sempre de Alto a Baixo para cada coluna de IDs em segundos, isso seria feito facilmente com:

sort -u -k2,2 infile

Caso contrário, você poderia fazer:

sed 's/High$/1/; s/Medium$/2/; s/Low$/3/' infile \
| sort -k2,3  \
| sort -uk2,2 \
| sed 's/1$/High/; s/2$/Medium/; s/3$/Low/'

Ou apenas com awk :

awk '{ pr[$2]=($3=="High"?$3:(pr[$2]=="High"?pr[$2]:(pr[$2]=="Medium"?pr[$2]:$3)));
       if (temp!=pr[$2]) { id[$2]=$0; temp=pr[$2] }
} END { for (key in id) print id[key] }' infile
    
por 21.09.2018 / 13:20
0

Eu usaria o Perl e criaria um analisador, que criaria esse hash:

  • valor da coluna 2 como a chave
  • primeira linha correspondente a uma chave constituiria o valor dessa chave
  • todas as outras linhas de uma chave serão ignoradas quando o valor for definido

Após a análise ser feita, eu imprimi o hash, classificando o segundo token, se necessário.

    
por 21.09.2018 / 13:20
0

Com apenas awk

awk '
    BEGIN {prio["High"]=1; prio["Medium"]=2; prio["Low"]=3}
    !($2 in p) || prio[$3] < p[$2] {p[$2] = prio[$3]; line[$2] = $0}
    END {for (key in line) print line[key]}
' file
id1 Disease1 High
id4 Disease2 Low
id5 Disease3 Medium
    
por 21.09.2018 / 14:23

Tags