Perl不匹配正则表达式?

3

我正在尝试移除一堆SGF文件中的所有注释,并想出了以下Perl命令:

perl -pi -e 's/P?C\[(?:[^\]\\]++|\\.)*+\]//gm' *.sgf

我正在尝试匹配并删除一个C或PC后跟一个左括号,然后是不是右括号的字符(如果它们是的话,必须用\转义),然后是右括号。

我正在尝试匹配以下示例:

C[HelloBot9 [-\]: GTP引擎用于HelloBot9(白色):HelloBot版本0.6.26.08]

PC[IA [-\]: GTP Engine for IA (black): GNU Go version 3.7.11
]

C[person [-\]: \\\]]

C[AyaMC [3k\]: GTP Engine for AyaMC (black): Aya version 6.61 : If you pass, AyaMC 
will pass. When AyaMC does not, please remove all dead stones.]

以下是不应匹配的一些示例:

XYZ[其他内容\]]

C[内容\]

PC[内容\\\]

该正则表达式在几个在线正则表达式测试工具中(包括一些声称它们是Perl正则表达式测试工具的工具)都有效,但由于某种原因,在命令行上无法正常工作。希望得到帮助。


1
我看到的所有在线正则表达式测试工具都使用PCRE而不是Perl正则表达式,因此结果可能不同。此外,/m修饰符是无用的,因为您没有使用任何^$锚点,请参见perlre - ThisSuitIsBlackNot
当我在第一组示例上运行您的代码时,它可以工作。您能否创建一个 [mcve]? - ThisSuitIsBlackNot
1
你能更新一下你问题中的例子吗?我猜你的意思是C[...]中间有一个换行符,如果是这样的话,我会参考这个问题 - ThisSuitIsBlackNot
1
所以,你使用了 perl -0777pi -e 并且它起作用了吗?另外,一个稍微优化的模式看起来像是 s/P?C\[[^]\\]*(?:\\.[^]\\]*+)*]//sg(如果换行符不能被转义,在这种情况下甚至不需要 s 修饰符)。 - Wiktor Stribiżew
@WiktorStribiżew 是的,那就是我用的。谢谢你提供了优化版,但对我来说并不是必须的。我使用的perl命令在一个包含35K个文件的目录中执行需要的时间是可以接受的(如果我猜测的话,最多需要2分钟);然而,如果你愿意,你可以将它作为答案发布,以帮助其他需要的人。 - takra
显示剩余3条评论
1个回答

2

您需要使用-0777选项运行perl,以确保可以找到跨越多行并匹配模式的内容。因此,使用perl -0777pi -e而不是perl -pi -e将解决该问题。

我还建议通过展开替代组来优化模式,从而使匹配过程“线性”:

s/P?C\[[^]\\]*(?:\\.[^]\\]*+)*]//sg

请注意,如果要将PC作为一个完整的单词匹配,需要在P前面添加\b模式详细信息
  • P?C\[ - 匹配PC[C[这个字符序列
  • [^]\\]* - 零个或多个不包含\]的字符
  • (?:\\.[^]\\]*+)* - 零个或多个以下序列:
    • \\. - 匹配\字符且后跟任意字符 (.)
    • [^]\\]*+ - 匹配零个或更多不包括]\字符(贪婪匹配,不会回溯到模式中)
  • ] - 匹配]字符(请注意,在字符类外部它不必转义以表示文字闭合括号)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接