2

再次提出一些问题。我有一个格式的文件:

>seq1
123 234 56
167 332 22
23 456 098
>seq2
123 234 56
167 332 22
23 456 098

我想要一个文件保存每个 >seq#,如下所示:

文件 1:

>seq1
123 234 56
167 332 22
23 456 098

文件 2:

>seq2
123 234 56
167 332 22
23 456 098

我可以使用 perl 脚本,但想知道如何使用 perl 单行器来完成,只是为了增加我的 perl 知识。

谢谢!!

4

2 回答 2

2

这是一个完成这项工作的相当小的脚本:

use strict;
use warnings;
my $fh = *STDOUT;

while (<>)
{
    chomp;
    if (m/^>/)
    {
        close $fh;
        open $fh, $_ or die "Failed to open $_";
    }
    print $fh "$_\n";
}

my $fh = *STDOUT;行表示如果第一>file行之前有内容,则将其回显到标准输出。

以此为基础,您可以决定将其展平为一行,忽略错误、关闭打开的文件、限制和可读性:

perl -e 'while(<>){chomp;open$f,$_ if(m/^>/);print$f "$_\n";}'

不过,我不可能推荐那个。(是的,两个空格都是必需的。)

于 2013-07-19T00:45:14.897 回答
2

看着乔纳森的答案,我想出了一些奇怪的东西来发布一个新的答案。我想补充一点,这应该被视为一个练习示例(也许是混淆),而不是任何正确的代码。该解决方案的全部功劳归于 Jonathan。此外,如底部所述,这是一个危险的解决方案。

perl -ple 'open STDOUT, $_' yourfile.txt

这依赖于Jonathan发现>seq1的旧 2-argument开头的行。例如将创建(覆盖)并打开文件进行写入。openopen $fh, ">seq1"seq1

同时,任何没有有效“模式”符号的行—— <,>|——将默认打开以供阅读,如果我们押注其中不123 234 56存在具有名称等的文件这一事实目录,我们可以依靠我们open的静默失败并维护先前打开的STDOUT文件句柄。

通过使用该-l选项,我们不需要chomp $_使open不会失败,也不需要在打印中添加换行符。同时,该-p选项将负责创建while循环并进行打印。

因为默认情况下打印到STDOUT,所以我们需要做的就是重新打开STDOUT文件句柄,输入文件的内容负责其余的工作。

这个单行代码的完整代码带有注释以表示哪些部分来自哪个开关:

BEGIN { $/ = "\n"; $\ = "\n"; }    # -l, gives newlines to print
while (<>) {                       # -p 
    chomp $_;                      # -l
    open STDOUT, $_;               # our code
}
continue {
    print STDOUT $_;               # -p
}

注意:此代码将释放open命令的全部功能,这很危险,因为在这种情况下,允许在您的文件系统上执行任意命令。这是允许使用 2-argument open 的副作用。

于 2013-07-19T02:05:13.007 回答