perl one-liner用于分割每个给定单词的文件

时间:2013-07-19 00:08:14

标签: perl file split

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

>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知识。

谢谢!

2 个答案:

答案 0 :(得分: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";}'
但是,我不太可能推荐这个。 (是的,两个空白都是必要的。)

答案 1 :(得分:2)

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

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

这取决于以>seq1开头的行与Jonathan发现的旧2参数open一起使用。例如。 open $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参数打开的副作用。