【问题标题】:regex replace in a file正则表达式替换文件
【发布时间】:2013-01-12 22:00:08
【问题描述】:

我正在尝试用 Perl 替换文件中的一组特定字符,但它似乎不起作用,这是我的代码。

my $file = shift;
open(FILE, "$file") or die "File not found";
while (<FILE>){
   $data .=$_
}
$data =~ s/[^A-CEGHJ-PR-TW-Z]{1}[A-CEGHJ-NPR-TW-Z]{1}\s?[0-9]{2}\s?[0-9]{2}\s[0-9]{2}\s?[A-DEM]{0,1}$/XX012345X/g;

我知道我的模式匹配适用于查找字符集,但我不完全确定替换是否有效。然而,我主要关心的是 Perl 代码。该文件在我运行后保持不变。

示例文件。

AB123456C Ab12345678 DG657465 GH123456FG

【问题讨论】:

  • 你能在你的问题中发布一个示例文件吗?
  • 1.您不写入该文件,您只是从中读取数据,那么为什么要更改文件? 2.您的正则表达式使用锚来匹配字符串的开头和结尾,您读取多行,可能您需要m 修饰符来更改该行为?
  • 也许你应该提到你希望你的代码能做什么。除非您打印 $data,否则此代码不会执行任何操作。此外,在您的正则表达式的第一部分,您有 Z{1},这看起来像是一个错字。
  • 哦,而且“它不起作用”是描述您的问题的一种非常糟糕的方式。它并没有真正说什么,是吗。
  • "运行后文件保持不变。"回答那个。所做的编辑。我的意图在第一行很清楚,但为了清楚起见,我正在尝试打开一个文件,对整个文件执行替换正则表达式。谢谢

标签: regex perl file


【解决方案1】:

您正在打开的文件是只读的。因此,您需要打开一个临时的第二个文件 (File::Temp),在其中写入 $data 变量,关闭它,删除第一个文件 (unlink) 和 rename 将临时文件改成所需的名称。

这个SO question 可能会有所帮助。

题外话:请使用现代 Perl 方法来处理您的文件。例如:

open my $fh, "<", $filename or die "Cannot open file $filename"

另见SO question。避免使用包全局类型全局文件句柄。

【讨论】:

    【解决方案2】:

    代码不会更改文件,因为您没有告诉它这样做。您打开文件是为了读取,而不是写入,而且您不打印任何内容。

    如果您想快速处理此问题,只需将您的正则表达式替换放在一个文件中并将其用作源文件。像这样:

    regex.pl 的内容:

    s/[^A-CEGHJ-PR-TW-Z]{1}[A-CEGHJ-NPR-TW-Z]{1}\s?[0-9]{2}\s?[0-9]{2}\s[0-9]{2}\s?[A-DEM]{0,1}$/XX012345X/g;
    

    单线:

    perl -p regex.pl inputfile.txt > output.txt
    

    这样您可以快速检查输出。您也可以通过管道传送到寻呼机命令或根本不传送。

    【讨论】:

    • 好的,谢谢。我喜欢一行一行的想法。我已经被正则表达式稍微修改了。现在是/^[A-CEGHJ-PR-TW-Z]{1}[A-CEGHJ-NPR-TW-Z]{1}[0-9]{6}[A-DFM]{0,1}$/,在正则表达式测试器网站中匹配时,它非常适合AB123456C。当我通过添加 /XX01234X/g 将其更改为替换时,它似乎不起作用。有什么想法吗?
    • 这在删除^$ 后现在似乎可以工作了。有什么办法可以避免管道进入另一个文件而只修改原始文件?
    • 是的,您可以使用-i 开关,它将就地编辑。建议使用备份,例如-i.bak(备份保存在file.txt.bak)。所以perl -pi.bak regex.pl input.txt
    • 我通常不建议初学者使用-i 切换,因为它有些危险。这些更改是不可逆的,即使您使用备份,也可以通过运行脚本两次来覆盖您的原始文件(file.txt.bak 被覆盖)。
    猜你喜欢
    • 2018-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    • 2019-01-24
    • 2015-01-24
    相关资源
    最近更新 更多