Extrai o número do comprimento n do campo e da string de retorno

6

Eu tenho um arquivo delimitado por tabulações com uma combinação de texto e números. Eu quero manter cada linha como está, mas quero manter apenas os números de seis dígitos na quinta coluna, se presentes. Por exemplo:

gene1   NM_033629   598G>A  P912    syndrome  1, 192315 syndrome 2,  225750 syndrome 3 610448   score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   syndrome 1 600195   score   AD  rec user    234567  Source

(a síndrome # é usada como exemplo, pode ser qualquer texto, não um padrão que eu possa pesquisar e remover)

Eu quero que a saída seja:

gene1   NM_033629   598G>A  P912    192315 225750 610448    score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   600195  score   AD  rec user    234567  Source

Eu tenho 4 maneiras de extrair o número de 6 dígitos, no entanto, não posso

a. output o número na linha que originou de

b. imprima com sucesso a linha inteira com o campo editado. As opções que usei para extrair os dígitos são:

cat inputfile | cut -f 5 |grep -P '(? < !\d)\d{6}(?!\d)'
cat inputfile | cut -f 5 |grep -Po '(?< !\d)\d{6}(?!\d)'
cat inputfile | cut -f 5 |grep -o '[[:digit:]]*'
cat inputfile | cut -f 5 |grep -o "[0-9]\{6\}"

Eu sei que o uso de corte para a coluna está incorreto, mas eu queria garantir que eu tivesse o extrato correto, pois há também um número de seis dígitos no campo 9. Estou empenhado em juntar tudo isso. Agradecemos antecipadamente por qualquer sugestão

    
por DemosW 11.10.2017 / 18:11

2 respostas

3

Se bem entendi, você quer que a quinta coluna se torne a concatenação com espaço de todos os números de 6 dígitos.

Talvez:

perl -F'\t' -lape '
   $F[4] = join " ", grep {length == 6} ($F[4] =~ /\d+/g);
   $_ = join "\t", @F' < file

Ou reutilize seu olhar negativo em torno dos operadores:

perl -F'\t' -lape '
   $F[4] = join " ", ($F[4] =~ /(?<!\d)\d{6}(?!\d)/g);
   $_ = join "\t", @F' < file

com awk :

awk -F'\t' -v OFS='\t' '
  {
    repl = sep = ""
    while (match($5, /[0-9]+/)) {
      if (RLENGTH == 6) {
        repl = repl sep substr($5, RSTART, RLENGTH)
        sep = " "
      }
      $5 = substr($5, RSTART+RLENGTH)
    }
    $5 = repl
    print
  }' < file

grep em si não é muito adequado para a tarefa. grep destina-se a imprimir as linhas que correspondem a um padrão. Algumas implementações como GNU ou ast-open grep , ou pcregrep podem extrair strings das linhas correspondentes, mas isso é bastante limitado.

A única abordagem cut + grep + paste que posso pensar que poderia funcionar com algumas restrições seria com a implementação pcregrep grep :

n='(?:.*?((?1)))?'
paste <(< file cut -f1-4) <(< file cut -f5 |
  pcregrep --om-separator=" " -o1 -o2 -o3 -o4 -o5 -o6 -o7 -o8 -o9 \
    "((?<!\d)\d{6}(?!\d))$n$n$n$n$n$n$n$n"
  ) <(< file cut -f6-)

Isso pressupõe que cada linha de entrada tenha pelo menos 6 campos e que o 5º campo de cada um tenha entre 1 e 9 números de 6 dígitos.

    
por 11.10.2017 / 18:30
0
awk '
BEGIN {
    FS = "\t";
    OFS = "\t";
}
{
    cnt = patsplit($5, arr, /[0-9]{6}/);
    $5 = arr[1];
    for(i = 2; i <= cnt; i++) {
        $5 = $5 " " arr[i];
    }
    print;
}' input.txt

patsplit(s, a [, r [, seps] ]) - Split the string s into the array a and the separators array seps on the regular expression r, and return the number of fields. Element values are the portions of s that matched r.

Entrada:

gene1   NM_033629   598G>A  P912    syndrome 1, 192315 syndrome 2, 225750 syndrome 3 610448 score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   syndrome 1 600195   score   AD  rec user    234567  Source

Saída:

gene1   NM_033629   598G>A  P912    192315 225750 610448    score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   600195  score   AD  rec user    234567  Source
    
por 11.10.2017 / 22:09