Código Perl para dividir um arquivo, se 16s e 23s estiverem presentes. e copie em um único arquivo

0

Eu tenho um arquivo do qual eu quero procurar pela string "16S" e "23S" e extrair a seção contendo essas strings em dois arquivos separados.

Arquivo de entrada:

start
description Human 16S rRNA
**some text**
**some text**
//
start
description Mouse 18S rRNA
some text
some text
//
start
description Mouse 23S rRNA
some text
some text
//

Saída esperada: Arquivo1 para 16S:

start
description Human 16S rRNA
some text
some text
//

Arquivo2 para 23S:

start
description Mouse 23S rRNA
some text
some text
//

Meu código usado:

#! /usr/bin/perl   
# default output file is /dev/null - i.e. dump any input before
# the first [ entryN ] line.

$outfile='FullrRNA.gb';
open(OUTFILE,">",$outfile) || die "couldn't open $outfile: $!";

while(<>) {
  # uncomment next two lines to optionally remove comments (startin with
  # '#') and skip blank lines.  Also removes leading and trailing
  # whitespace from each line.
  # s/#.*|^\s*|\s*$//g;
  # next if (/^$/)

  # if line begins with 'start', extract the filename
  if (m/^\start/) {
    (undef,$outfile,undef) = split ;
    close(OUTFILE);
    open(OUTFILE,">","$outfile.txt") || die "couldn't open $outfile.txt: $!";
  } else {
    print OUTFILE;
  }
}
close(OUTFILE);
    
por Code explore 28.08.2017 / 11:09

2 respostas

0

Se você pode confiar em <LF>//<LF> como um separador de registro, então com o GNU awk , pode ser apenas:

gawk -v 'RS=\n//\n' '
  {ORS=RT}; / 16S /{print > "file1"}; / 23S /{print > "file2"}' < file
    
por 28.08.2017 / 12:33
1

Eu resolveria isso com awk em vez de Perl, desculpe.

/^\/\// && file { file = file ".out";
                  print section ORS $0 >file;
                  file = "" }

/^description/ && match($0, p) && file = substr($0,RSTART,RLENGTH) {}

/^start/        { section = $0; next       }
                { section = section ORS $0 }

Executando em seus dados (você usa p='expression' para escolher as seções que deseja):

$ awk -f script.awk p='16S|23S' file.in
$ ls -l
total 16
-rw-r--r--  1 kk  wheel   64 Aug 28 12:10 16S.out
-rw-r--r--  1 kk  wheel   56 Aug 28 12:10 23S.out
-rw-r--r--  1 kk  wheel  176 Aug 28 11:51 file.in
-rw-r--r--  1 kk  wheel  276 Aug 28 12:09 script.awk
$ cat 16S.out
start
description Human 16S rRNA
**some text**
**some text**
//
$ cat 23S.out
start
description Mouse 23S rRNA
some text
some text
//

O primeiro bloco no script é executado se encontrarmos um marcador de fim de seção (uma linha começando com // ) e se o nome do arquivo de saída ( file ) estiver não vazio. Ele anexa .out ao nome do arquivo atual e gera a saída da seção salva, seguida da linha de entrada atual no arquivo. Em seguida, ele esvazia a variável file .

O segundo bloco está vazio, mas o padrão corresponderá às linhas que começam com description e irá corresponder a linha à expressão regular dada na linha de comando ( p ). Se corresponder, a parte correspondente será escolhida e usada como o nome do arquivo.

O terceiro bloco é executado se encontrarmos uma linha que começa com a palavra start e apenas define o texto da seção salva na linha atual, descartando qualquer texto antigo salvo nela. Em seguida, pula para o início do script e considera a próxima linha de entrada.

O último bloco é executado para todas as outras linhas no arquivo e ele anexa a linha atual à seção atualmente salva.

    
por 28.08.2017 / 12:16

Tags