Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 基于文件内容和模式匹配拆分文件_Linux_Perl_Bash_Pattern Matching - Fatal编程技术网

Linux 基于文件内容和模式匹配拆分文件

Linux 基于文件内容和模式匹配拆分文件,linux,perl,bash,pattern-matching,Linux,Perl,Bash,Pattern Matching,我需要你的帮助,用bash/linux格式化一个txt文件。该文件如下所示,它始终有一行名为Rate:Sth,然后以非常具体的格式显示细节。我想把这个文件分成两部分,每个文件一个费率。在本例中,我希望有3个文件,每个文件都有相应的行,表示速率值是多少 你将如何处理这个问题 line No. Main Text 1 Rate: GBP 2 12/01/1999,90.5911501,Validated ..... ..... 210 18/01/1999,90.9

我需要你的帮助,用bash/linux格式化一个txt文件。该文件如下所示,它始终有一行名为Rate:Sth,然后以非常具体的格式显示细节。我想把这个文件分成两部分,每个文件一个费率。在本例中,我希望有3个文件,每个文件都有相应的行,表示速率值是多少

你将如何处理这个问题

line No. Main Text
1    Rate: GBP
2    12/01/1999,90.5911501,Validated
     .....
     .....
210  18/01/1999,90.954996,Validated
211  Rate: RMB
212  24/04/2008,132.2542,Validated
     .....
1000 25/04/2008,132.2279,Validated
1001 28/04/2008,131.69915,Validated
1002 Rate: USD
1003 21/11/11,-0.004419534,Validated
我会用perl实现这一点:

#!/usr/bin/perl

use strict;
use warnings;

open (my $out, ">-") or die "oops";

while(<>)
{
    if (m/^Rate: (\w+)/o)
    {
        close $out and open ($out, ">$1") or die "oops";
        next;
    }

    print $out $_
}

另一种解决方案:它只是将您的输入文件制作成脚本,然后运行它:

sed 's/^Rate:/cat <<EOF >/; 1!s/^cat <<EOF/EOF\n&/; $aEOF' input.txt | bash

sed的/^Rate:/cat您可以在perl中使用类似的内容-

Perl脚本:

#!/usr/bin/perl

undef $/;
$_ = <>;
$n = 0;

for $match (split(/(?=Rate)/)) {
      open(O, '>temp' . ++$n);
      print O $match;
      close(O);
}
[jaypal~/temp]$ ./spl.pl temp.file

[jaypal~/temp]$ **cat temp.file**
Line No. Main Text
1    Rate: GBP
2    12/01/1999,90.5911501,Validated
     .....
     .....
210  18/01/1999,90.954996,Validated
211  Rate: RMB
212  24/04/2008,132.2542,Validated
     .....
1000 25/04/2008,132.2279,Validated
1001 28/04/2008,131.69915,Validated
1002 Rate: USD
1003 21/11/11,-0.004419534,Validated

[jaypal~/temp]$ cat temp1
Line No. Main Text
1    

[jaypal~/temp]$ cat temp2
Rate: GBP
2    12/01/1999,90.5911501,Validated
     .....
     .....
210  18/01/1999,90.954996,Validated

211  

[jaypal~/temp]$ cat temp3
Rate: RMB
212  24/04/2008,132.2542,Validated
     .....
1000 25/04/2008,132.2279,Validated
1001 28/04/2008,131.69915,Validated

1002 [jaypal~/temp]$ cat temp4
Rate: USD
1003 21/11/11,-0.004419534,Validated
[jaypal~/temp]$ 
(g)awk
救援:

awk '/^Rate:/ {output_file_name=$2; getline } 
     { print $0 >> ( output_file_name ) }' INPUT_FILE
第一条规则和命令对以
Rate:
开头的行执行,只设置输出文件名,然后从输入文件中获取下一行。然后处理下一行并将其写入输出文件。之后,下一行仅由第二个命令(写入输出文件)处理,但前提是它与
Rate:
不匹配

注意:如果输入文件中有两行连续的
Rate:
s,则上述解决方案可能会失败,如下所示:

... DATA ...
Rate: GBP
Rate: CHF
... DATA ...
应该这样做(假设行号不是原始文件的一部分)


HTH

一句话的灵感来源于sehe的回答:

>perl -pwe '
> if (/^Rate: (.+)/) { 
>    open $out, ">", "Rate_$1.txt" or die $!; 
>    select $out; 
> }' gasdata.txt
计算
-e
中的代码后,
-p
选项将读取一行并打印它<代码>选择
将为
打印
选择默认文件句柄。因此,基本上,我们所做的只是简单地改变文件句柄,这取决于当前的活动速率

下面是被分解的代码:

>perl -MO=Deparse -pwe 'if (/^Rate: (.+)/) { open $out, ">", "output/Rate_$1.txt" or die $!; select $out; }' gasdata.txt
BEGIN { $^W = 1; }
LINE: while (defined($_ = <ARGV>)) {
    if (/^Rate: (.+)/) {
        die $! unless open $out, '>', "output/Rate_$1.txt";
        select $out;
    }
}
continue {
    die "-p destination: $!\n" unless print $_;
}
-e syntax OK
>perl-MO=Deparse-pwe'if(/^Rate:(.+)/){open$out,“>”、“output/Rate_$1.txt”或die$!;选择$out;}'gasdata.txt
开始{$^W=1;}
行:while(已定义($\u=)){
如果(/^费率:(.+)/){
die$!除非打开$out,“>”,“输出/速率_$1.txt”;
选择$out;
}
}
继续{
模具“-p目的地:$!\n”,除非打印$;
}
-e语法正常

这可能适合您:

csplit -z -f 'temp' -b '%02d.txt' file /Rate/ {*}
这将生成文件temp00.txt、temp01.txt

如果您只需要
Rate
行,那么

sed -i '/Rate/!d' temp*.txt

聪明的先开,让循环简洁。非常好。+1代表鼓舞人心的答案。请参阅我的答案,了解您想法的一行代码版本。只是为了澄清行号不是文件的一部分。我还希望输出文件包含速率:**Line。这不会在匹配模式后只得到一行吗?感谢Zsolt的解释。不知道为什么,但我仍然有运行一个班轮的问题。
print$0>>输出文件名不应该有
围绕
输出文件名
我喜欢这个解决方案!尤其是使用速率文本命名文件的方式。一个小的诡辩,但可能会节省一些头发-这里的文档将插入变量等默认情况下
s/^Rate:/cat一个小的调整,您也可以有
Rate…
行<代码>/^速率:/{h;s//…/;G}
sed -i '/Rate/!d' temp*.txt