2

我有一个充满文件的目录,我需要从它们中提取页眉和页脚。它们都是可变长度的,所以使用 head 或 tail 是行不通的。每个文件都有一行我可以搜索,但我不想在结果中包含该行。

通常是

*** Start (more text here)

并以

*** Finish (more text here)

我希望文件名保持不变,所以我需要覆盖原件,或者写入不同的目录,我会自己覆盖它们。

哦,是的,它当然是在 linux 服务器上,所以我有 Perl、sed、awk、grep 等。

4

7 回答 7

3

试试人字拖!“..“ 操作员。

# flip-flop.pl
use strict;
use warnings;

my $start  = qr/^\*\*\* Start/;
my $finish = qr/^\*\*\* Finish/;

while ( <> ) {
    if ( /$start/ .. /$finish/ ) {
        next  if /$start/ or /$finish/;
        print $_;
    }
}

然后你可以使用 -i perl 开关来更新你的文件,就像这样.....

 $ perl -i'copy_*' flip-flop.pl data.txt 

...这会更改 data.txt,但会事先将副本复制为“copy_data.txt”。

于 2008-11-17T19:54:14.060 回答
2

GNU coreutils 是你的朋友...

csplit inputfile %^\*\*\* Start%1 /^\*\*\* Finish/ %% {*}

这会将您想要的文件生成为xx00. --prefix您可以通过选项、--suffix和更改此行为--digits,但请自行查看手册。由于csplit设计用于生成多个文件,因此无法生成没有后缀的文件,因此您必须手动或通过脚本进行覆盖:

csplit $1 %^\*\*\* Start%1 /^\*\*\* Finish/ %% {*}
mv -f xx00 $1

根据需要添加循环。

于 2008-11-17T23:26:50.950 回答
1

要获取标题

cat yourFileHere | awk '{if (d > 0) print $0} /.*Start.*/ {d = 1}'

要获取页脚

cat yourFileHere | awk '/.*Finish.*/ {d = 1} {if (d < 1) print $0}'

根据需要从页眉到页脚获取文件:

cat yourFileHere | awk '/.*Start.*/ {d = 1; next} /.*Finish.*/ {d = 0; next} {if (d > 0) print $0}'

还有另一种方法,使用 csplit 命令,您应该尝试以下操作:

csplit yourFileHere /Start/ /Finish/

并检查名为 'xxNN' 的文件,其中 NN 是运行编号,还请查看csplit 手册页

于 2008-11-17T18:23:54.477 回答
0

也许?从不删除开始到完成。

$ sed -i '/^\*\*\* Start/,/^\*\*\* Finish/d!' *

或者......不太确定......但是,如果它有效,也应该删除 Start 和 Finish 行:

$ sed -i -e '/./,/^\*\*\* Start/d' -e '/^\*\*\* Finish/,/./d' *

d!可能取决于sed你的体型——不确定。
而且,我完全是在(可能很差)内存上写的。

于 2008-11-17T18:17:15.177 回答
0

一个快速的 Perl hack,未经测试。我在 sed 或 awk 方面不够流利,无法通过它们获得这种效果,但我会对如何做到这一点感兴趣。

#!/usr/bin/perl -w
use strict;
use Tie::File;
my $Filename=shift;  
tie my @File, 'Tie::File', $Filename or die "could not access $Filename.\n";  
while (shift @File !~ /^\*\*\* Start/) {};  
while (pop @File !~ /^\*\*\* Finish/) {};  
untie @File;  
于 2008-11-17T18:34:51.333 回答
0

覆盖原始文件的 Perl 解决方案。

#!/usr/bin/perl -ni
if(my $num = /^\*\*\* Start/ .. /^\*\*\* Finish/) {
    print if $num != 1 and $num + 0 eq $num;
}
于 2008-11-17T19:37:24.297 回答
0

perlfaq5中的一些示例:如何在文件中更改、删除或插入一行,或附加到文件的开头?可能会有所帮助。你必须使它们适应你的情况。此外,Leon 的触发器运算符答案是在 Perl 中执行此操作的惯用方式,尽管您不必修改文件即可使用它。

于 2008-11-17T22:52:31.690 回答