3

我有一堆包含半标准标题的文件。也就是说,它的外观非常相似,但文本有所变化。

我想从所有文件中删除此标头。

通过查看文件,我知道我要删除的内容被封装在相似的单词之间。

因此,例如,我有:

Foo bar...some text here...
more text
Foo bar...I want to keep everything after this point

我在 perl 中尝试了这个命令:

perl -pi -e "s/\A.*?Foo.bar*?Foo.bar//simxg" 00ws110.txt

但它不起作用。我不是正则表达式专家,但希望有人知道如何根据文本匹配而不是字符数从文件开头删除一大块文本......

4

4 回答 4

7

默认情况下,ARGV(又名<>在幕后使用-p)一次只读取一行。

解决方法:

  1. Unset $/,它告诉 Perl 一次读取整个文件。

    perl -pi -e "BEGIN{undef$/}s/\A.*?Foo.bar*?Foo.bar//simxg" 00ws110.txt
    

    BEGIN在第一次读取完成之前运行该代码是必要的。

  2. 使用-0,其中设置$/ = "\0"

    perl -pi -0 -e "s/\A.*?Foo.bar*?Foo.bar//simxg" 00ws110.txt
    
  3. 利用触发器运算符

    perl -ni -e "print unless 1 ... /^Foo.bar/'
    

    这将从第 1 行开始跳过打印到/^Foo.bar/.

于 2009-03-23T20:42:27.203 回答
3

如果你的标题超过一行,你必须告诉 perl 要读多少。如果文件与内存相比很小,您可能只想将整个文件放入内存中:

perl -0777pi.orig -e 's/your regex/your replace/s' file1 file2 file3

-0777选项将 perl 设置为 slurp 模式,因此$_每次循环都会保存每个整个文件。另外,请始终记住设置备份扩展名。如果你不这样做,你可能会发现你已经不小心删除了你的数据并且无法取回它。有关perldoc perlrun更多信息,请参阅。

鉴于评论中的信息,您似乎正试图从Project Gutenberg电子书的前面去除所有烦人的东西。如果你了解所有涉及的版权问题,你应该可以像这样摆脱前面的事情:

perl -ni.orig -e 'print unless 1 .. /^\*END/' 00ws110.txt

Project Gutenberg 标题以

*END*THE SMALL PRINT! FOR PUBLIC DOMAIN ETEXTS*Ver.04.29.93*END*

更安全的正则表达式也会考虑到*END*行尾的,但我很懒。

于 2009-03-23T20:49:20.603 回答
2

我可能会误解您的要求,但在我看来很简单:

perl -ni -e 'print unless 1..($. > 1 && /^Foo bar/)'
于 2009-03-23T21:19:35.447 回答
0

干得好!这将替换文件的第一行:


use Tie::File;

tie my @array,"Tie::File","path_to_file" or die("can't tie the file");
$array[0] =~s/text_i_want_to_replace/replacement_text/gi;
untie @array;

您可以对数组进行操作,您将看到数组中的修改。您可以从数组中删除元素,它将从文件中删除该行。对元素应用替换将替换行中的文本。

如果你想删除前两行,并保留第三行的内容,你可以这样做:


# tie the @array before this
shift @array;
shift @array;
$array[0]=~s/foo bar\.\.\.//gi;
# untie the @array

这将完全满足您的需求!

于 2009-03-23T20:29:20.200 回答