Usando sed
:
sed -n '/^chr10[^0-9]/ { p; b; }; q' cov.txt > subset.txt
Isso ainda pressupõe que o chr10
group está no início do arquivo.
Eu tenho um arquivo enorme que se parece com isso
chr10 98072 1
chr10 98073 1
chr10 98074 1
chr10 98075 2
chr10 98076 2
chr10 98077 3
chr10 98078 5
chr10 98079 5
chr11 98080 5
chr12 98081 5
Eu tenho muitas entradas para cada cromossomo. Eu só quero extrair linhas que tenham chr10. Como meu arquivo é muito grande, usei este comando para extrair apenas as linhas chr10
awk '$1 ~ /^chr10$/{print}; $1 !~ /^chr10$/{exit}' cov.txt > subset.txt
Esta é uma boa maneira de fazer o awk não passar pelo arquivo inteiro. Meu arquivo já está classificado no cromossomo
Obrigado
awk '$1=="chr10"{print; next}{exit}' cov.txt > subset.txt
Testes: Redirecionados para /dev/null
para > 12.947.909 chr10
registros mais mais alguns chr11
, chr12
e mais para um total de 99.063.774 linhas - saídas são todas idênticas (mesmo md5sum). A contagem da linha de saída = 12.947.909 - ordenou a mais rápida a mais lenta:
steve: awk '{ if($1 == "chr10") { print } else { exit } }' cov.txt >/dev/null
real 0m5.963s
user 0m5.896s
sys 0m0.064s
Peter.O: awk '$1=="chr10"{print; next}{exit}' cov.txt >/dev/null
real 0m6.553s
user 0m6.484s
sys 0m0.068s
kos: perl -pe '!/chr10/&&exit' cov.txt >/dev/null
real 0m8.658s
user 0m8.545s
sys 0m0.112s
steve: sed -n '/^chr10[^0-9]/ { p; b; }; q' cov.txt >/dev/null
real 0m17.130s
user 0m17.077s
sys 0m0.052s
user3138373: awk '$1 ~ /^chr10$/{print}; $1 !~ /^chr10$/{exit}' cov.txt >/dev/null
real 0m18.621s
user 0m18.541s
sys 0m0.080s
Tente isso, pareceu um pouco mais rápido no meu teste rudimentar. Evita o processamento regular de expressões.
[root@localhost tmp]# wc -l cov.txt
34970568 cov.txt
[root@localhost tmp]# time awk '$1 ~ /^chr10$/{print}; $1 !~ /^chr10$/{exit}' cov.txt > subset.txt
real 0m23.897s
user 0m22.031s
sys 0m1.556s
[root@localhost tmp]# time awk '{ if($1 == "chr10") { print } else { exit } }' cov.txt > subset.txt
real 0m16.784s
user 0m14.731s
sys 0m1.661s
[root@localhost tmp]#
Tentei a abordagem sed de lcd047 também
[root@localhost tmp]# time sed -n '/^chr10[^0-9]/ { p; b; }; q' cov.txt > subset.txt
real 0m38.343s
user 0m36.609s
sys 0m1.546s
[root@localhost tmp]#
Usando o grep antigo, o mais rápido, apesar de ler o arquivo inteiro
[root@localhost tmp]# time grep "^chr10" cov.txt >subset.txt
real 0m6.546s
user 0m4.932s
sys 0m1.577s
[root@localhost tmp]#
Teria pensado grep -F para ser mais rápido novamente, mas não parecia ser. Consistentemente por mais de 7 segundos.
[root@localhost tmp]# time grep -F chr10 cov.txt >subset.txt
real 0m7.317s
user 0m6.109s
sys 0m1.173s
[root@localhost tmp]#
Mais eficientemente, faça isso com egrep
:
egrep '^chr10{space or tab}' cov.txt
Ou se o conteúdo for parecido com o que você mostrou,
grep -w chr10 cov.txt
Como o arquivo está classificado e de acordo com seu comentário , as linhas que começam com chr10
estão sempre no início do arquivo, usando Perl:
< cov.txt perl -pe '!/chr10/&&exit' > subset.txt
Desta forma, o script sairá na primeira ocorrência de um não-correspondência.
Um teste dessa execução em um arquivo de linha de correspondência de 1000000 armazenado na memória (obtido ao anexar o chr10 98072 1
linha 1000000 vezes a um arquivo vazio) é executado em pouco tempo:
~/tmp$ < cov.txt wc -l
1000000
~/tmp$ time < cov.txt perl -pe '!/chr10/&&exit' > subset.txt
real 0m0.631s
user 0m0.624s
sys 0m0.004s
~/tmp$ < subset.txt wc -l
1000000
Tags awk