
Como recolher categorias KO com o mesmo nome e imprimir nomes de genes que foram atribuídos a cada categoria na matriz, como no exemplo abaixo.
Eu tenho isto:
K00002 gene_65472
K00002 gene_212051
K00002 gene_403626
K00003 gene_666
K00003 gene_5168
K00003 gene_7635
K00003 gene_12687
K00003 gene_175295
K00003 gene_647659
K00003 gene_663019
K00004 gene_88381
K00005 gene_30485
K00005 gene_193699
K00005 gene_256294
K00005 gene_307497
E quero isso:
K00002 gene_65472 gene_212051 gene_403626
K00003 gene_666 gene_5168 gene_7635 gene_12687 gene_175295 gene_647659 gene_663019
K00004 gene_88381
K00005 gene_30485 gene_193699 gene_256294 gene_307497
O seguinte comando funcionou (retirado deresposta de Roaima):
tr -d '\r' < file| awk '$1 != p { if (p>"") {printf "\n"} printf "%s",$1; p=$1 } { printf "\t%s",$2 } END { if(p>"") {printf "\n"} }' > output
Responder1
Mais do mesmo
awk '$1 != p { if (p>"") {printf "\n"} printf "%s",$1; p=$1 } { printf "\t%s",$2 } END { if(p>"") {printf "\n"} }' datafile
K00002 gene_65472 gene_212051 gene_403626
K00003 gene_666 gene_5168 gene_7635 gene_12687 gene_175295 gene_647659 gene_663019
K00004 gene_88381
K00005 gene_30485 gene_193699 gene_256294 gene_307497
Se você não quer a separação porabaem seguida, altere \t
para um espaço.
Veja como funciona:
# Each line is processed in turn. "p" is the previous line's key field value
# Key field isn't the same as before
$1 != p {
# Flush this line if we have printed something already
if (p > "") { printf "\n" }
# Print the key field name and set it as the current key field
printf "%s", $1; p = $1
}
# Every line, print the second value on the line
{ printf "\t%s", $2 }
# No more input. Flush the line if we have already printed something
END {
if (p > "") { printf "\n" }
}
Devago comentáriosvocê éfazendocontra as respostas de todos, parece que o problema subjacente é que você está usando um arquivo de dados gerado em um sistema Windows e espera que ele funcione em uma plataforma UNIX/Linux. Não faça isso. Ou, se necessário, primeiro converta o arquivo para o formato correto.
dos2unix < datafile | awk '...' # As above
tr -d '\r' < data file | awk '...' # Also as above
Responder2
arquivo:
K00002 gene_65472
K00002 gene_212051
K00002 gene_403626
K00003 gene_666
K00003 gene_5168
K00003 gene_7635
K00003 gene_12687
K00003 gene_654221
K00003 gene_663019
K00004 gene_88381
K00005 gene_30485
K00005 gene_193699
K00005 gene_256294
Usando o awk:
awk '1 {if (a[$1]) {a[$1] = a[$1]" "$2} else {a[$1] = $2}} END {for (i in a) { print i,a[i]}}' file
saída:
K00002 gene_65472 gene_212051 gene_403626
K00003 gene_666 gene_5168 gene_7635 gene_12687 gene_654221 gene_663019
K00004 gene_88381
K00005 gene_30485 gene_193699 gene_256294
Eu peguei issopublicarcomo referência.
Responder3
usando Millerhttp://johnkerl.org/miller/doc
com
mlr --csv --implicit-csv-header --headerless-csv-output cat -n -g 1 then label a,b,c then reshape -s a,c then unsparsify --fill-with "" input.csv
e este exemplo de entrada csv
A,234
A,4945
B,8798
B,8798
B,790
Voce terá
A,234,4945,
B,8798,8798,790
Responder4
Supondo que seus valores não contenham espaços e sejam separados por espaços; assumindo também que seus dados estão em um arquivo chamado file
(veja abaixo uma versão separada por tabulações):
for x in $(<file cut -d ' ' -f 1 | sort | uniq); do
printf '%s %s\n' "$x" "$(grep "$x" file | cut -d ' ' -f 2- | tr '\n' ' ' | sed 's/.$//')"
done
Isso vai:
- Extraia os valores distintos do primeiro campo:
cut
seleciona apenas o primeiro pedaço (-f 1
) de uma linha, quebrando-o a cada espaço (-d ' '
);sort | uniq
classificará os valores do primeiro campo e gerará cada um deles apenas uma única vez (alternativamente,mais curto e mais eficiente:sort -u
);
- Para cada:
- Extraia todas as linhas relevantes de
file
withgrep
; - Retire o primeiro campo deles com
cut
(-f 2-
significa "pegar o segundo campo e os seguintes"); - Traduza o restante em uma lista de valores separados por espaço (
tr
); - Livre-se do último caractere - um espaço desnecessário - usando
sed
(sim, isso é realmente deselegante); - Concatene o resultado ao valor do primeiro campo e imprima na saída padrão.
- Extraia todas as linhas relevantes de
Se sua entrada for separada por tabulações e você desejar uma saída separada por tabulações, o código acima se tornará:
for x in $(<file cut -f 1 | sort | uniq); do
printf '%s\t%s\n' "$x" "$(grep "$x" file | cut -f 2- | tr '\n' '\t' | sed 's/.$//')"
done
Notas:
- Desempenho: o tempo de execução para esta abordagem é significativamente maior do que o da
awk
soluções baseadas (testeiresposta de Roaima). Pelo menos de uma ordem de grandeza. - Por outro lado, esta abordagem funciona mesmo se o arquivo de entrada não estiver ordenado.
- Apesar desse tipo de solução ser uma maneira rápida (e suja?) de realizar o trabalho com eficácia, geralmente não é aconselhável processar texto com loops de shell; veja para referência "Por que usar um loop de shell para processar texto é considerado uma prática inadequada?".