用于分割文件的 Perl 代码(如果存在 16 秒和 23 秒)。并复制到一个文件中

用于分割文件的 Perl 代码(如果存在 16 秒和 23 秒)。并复制到一个文件中

我有一个文件,我想从中搜索字符串“16S”和“23S”,并将包含这些字符串的部分提取到两个单独的文件中。

输入文件:

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
//

预期输出:16S 的 File1:

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

23S 的文件2:

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

我使用的代码:

#! /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);

答案1

awk抱歉,我会用 Perl 来解决这个问题。

/^\/\// && 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 }

在您的数据上运行它(您可以用来p='expression'挑选您想要的部分):

$ 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
//

如果我们找到节结束标记(以 开头的行//)并且输出文件名 ( file) 非空,则执行脚本中的第一个块。它附加.out到当前文件名并将保存的部分输出到文件中,后跟当前输入行。然后它清空该file变量。

第二个块是空的,但该模式将匹配以 和 开头的行description,并将继续将该行与命令行 ( p) 上给出的正则表达式进行匹配。如果匹配,则匹配的部分将被挑选出来并用作文件名。

如果我们找到以该单词开头的行,则执行第三个块start,并且它只是将保存的节文本设置为当前行,并丢弃其中保存的任何旧文本。然后它跳到脚本的开头并考虑下一个输入行。

最后一个块针对文件中的所有其他行执行,并将当前行附加到当前保存的部分。

答案2

如果您可以依赖它<LF>//<LF>作为记录分隔符,那么使用 GNU awk,这可能只是:

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

相关内容