Dividir um arquivo em linhas com base em valores de coluna

2

O arquivo de entrada é parecido com isto:

chr1    1    G    300
chr1    2    A    500
chr1    3    C    200
chr4    1    T    35
chr4    2    G    400
chr4    3    C    435
chr4    4    A    223
chr4    5    T    400
chr4    6    G    300
chr4    7    G    340
chr4    8    C    400

O arquivo atual é muito grande para ser processado, portanto, desejo gerar uma filtragem de arquivo menor pelo cromossomo (coluna 1) e pela posição (coluna 2) dentro de um intervalo específico.

Por exemplo, estou procurando um comando do Linux (sed, awk, grep etc.) que filtrará chr4 das posições 3 a 7. A saída final desejada é:

chr4    3    C    435
chr4    4    A    223
chr4    5    T    400
chr4    6    G    300
chr4    7    G    340

Eu não quero modificar o arquivo original.

    
por cooldood3490 06.08.2017 / 21:33

4 respostas

8

A solução para o arquivo de entrada potencialmente não classificado:

sort -k1,1 -k2,2n file | awk '$1=="chr4" && $2>2 && $2<8'

A saída:

chr4    3    C    435
chr4    4    A    223
chr4    5    T    400
chr4    6    G    300
chr4    7    G    340

Se o arquivo de entrada estiver classificado, basta usar:

awk '$1=="chr4" && $2>2 && $2<8' file
    
por 06.08.2017 / 21:48
7

awk é provavelmente a melhor ferramenta para o trabalho. Uma solução simples, semelhante a uma já dada, mas que realmente usa os parâmetros que você especificou, é:

awk '$1=="chr4" && $2>=3 && $2<=7'

Você pode preferir uma solução mais geral, o que envolve colocar o comando awk em um script de shell, é:

#!/bin/sh
if [ "$#" -lt 3 ]
then
        echo "Usage:    $0 chromosome low_position high_position"
        exit 1
fi
chr="$1"
lo="$2"
hi="$3"
shift 3
awk -vchromo="$chr" -vpos1="$lo" -v pos2="$hi" '$1==chromo && $2>=pos1 && $2<=pos2' "$@"

Se for executado com menos de três argumentos, isso lembra quais devem ser os argumentos e sai. Caso contrário, ele salva os três primeiros argumentos em variáveis de shell, e, em seguida, desloca-os da lista de argumentos. Em seguida, ele invoca awk , passando os valores da variável shell como awk variables.

Você pode invocar isso como qualquer um dos seguintes:

./myscript chr4 3 7   data

ou

./myscript chr4 3 7 < data

ou

(some_other_process) | ./myscript chr4 3 7
e, em qualquer caso, redirecione a saída para o novo arquivo com > .     
por 06.08.2017 / 21:55
4

Você pode fazer isso com grep:

grep -e '^chr4\s\+[3-7]' input

em que expressão é: ^chr4 linhas começando com chr4, \s\+ um ou mais caractere de espaço, [3-7] corresponde a um dígito no intervalo de 3 a 7.

Talvez seja mais útil usar head ou tail para fornecer quantas linhas desejar, em vez de combiná-las com grep (usando grep apenas para corresponder à primeira coluna).

grep -e '^chr4\s\+' input| tail -n +3| head -n 5

grep corresponde a linhas que começam com chr4 , tail fornece linhas iniciando na terceira linha e usando head limite de saída nas primeiras 5 linhas (linhas 3 a 7).

    
por 06.08.2017 / 21:46
0

Você pode usar o utilitário split .

split -p 'chr4    (3|8)' -a 1 my_file output
  • split um arquivo em várias partes (basicamente o inverso de cat )
  • p para dividir na expressão regular estendida 'chr4 (3 | 8)'
  • -a 1 para sufixar os arquivos criados com um único caractere
  • output é o nome do prefixo de cada arquivo criado

Agora, o arquivo outputb conterá sua saída desejada. Você também pode modificar isso para colocar cada cromossomo em seu próprio arquivo.

    
por 06.08.2017 / 23:32