【问题标题】:Backslashes and escaping chars in Python vs Perl regexesPython 与 Perl 正则表达式中的反斜杠和转义字符
【发布时间】:2017-05-06 09:56:42
【问题描述】:

目标是处理 NLP 中的标记化任务,并将脚本从 Perl script 移植到 Python script

主要问题是当我们运行分词器的 Python 端口时会出现错误的反斜杠。

在 Perl 中,我们可能需要像这样对单引号和 & 符号进行转义:

my($text) = @_; # Reading a text from stdin

$text =~ s=n't = n't =g; # Puts a space before the "n't" substring to tokenize english contractions like "don't" -> "do n't".

$text =~ s/\'/\'/g;  # Escape the single quote so that it suits XML.

将正则表达式从字面上移植到 Python 中

>>> import re
>>> from six import text_type
>>> sent = text_type("this ain't funny")
>>> escape_singquote = r"\'", r"\'" # escape the left quote for XML
>>> contraction = r"n't", r" n't" # pad a space on the left when "n't" pattern is seen
>>> text = sent
>>> for regexp, substitution in [contraction, escape_singquote]:
...     text = re.sub(regexp, substitution, text)
...     print text
... 
this ai n't funny
this ai n\'t funny

& 符号的转义以某种方式将其添加为文字反斜杠 =(

要解决这个问题,我可以这样做:

>>> escape_singquote = r"\'", r"'" # escape the left quote for XML
>>> text = sent
>>> for regexp, substitution in [contraction, escape_singquote]:
...     text = re.sub(regexp, substitution, text)
...     print text
... 
this ai n't funny
this ai n't funny

但在 Python 中看似没有转义单引号,我们也得到了想要的结果:

>>> import re
>>> from six import text_type
>>> sent = text_type("this ain't funny")
>>> escape_singquote = r"\'", r"\'" # escape the left quote for XML
>>> contraction = r"n't", r" n't" # pad a space on the left when "n't" pattern is seen
>>> escape_singquote = r"'", r"'" # escape the left quote for XML
>>> text = sent
>>> for regexp, substitution in [contraction, escape_singquote]:
...     text = re.sub(regexp, substitution, text)
...     print text
... 
this ai n't funny
this ai n't funny

现在这令人费解......

鉴于上述上下文,问题是我们需要在 Python 中转义哪些字符以及在 Perl 中转义哪些字符? Perl 和 Python 中的正则表达式不是等效的吗?

【问题讨论】:

标签: python regex perl escaping tokenize


【解决方案1】:

在 Perl 和 Python 中,如果您想在字符类之外逐字匹配以下正则表达式元字符,则必须转义它们1

{}[]()^$.|*+?\

在字符类中,您必须根据这些规则对元字符进行转义2

     Perl                          Python
-------------------------------------------------------------
-    unless at beginning or end    unless at beginning or end
]    always                        unless at beginning
\    always                        always
^    only if at beginning          only if at beginning
$    always                        never

请注意,无论是在字符类内部还是外部,单引号 ' 和 & 符号 & 都不得转义。

但是,如果您使用它来转义不是元字符的标点符号,Perl 和 Python 都会忽略反斜杠(例如,\' 等同于正则表达式中的 ')。


你似乎被 Python 的raw strings 绊倒了:

当存在'r''R' 前缀时,反斜杠后面的字符将原样包含在字符串中,并且所有反斜杠都保留在字符串中。

r"\'" 是字符串\'(文字反斜杠,文字单引号),而r'\'' 是字符串\'(文字反斜杠,文字和符号等)。

所以这个:

re.sub(r"\'", r'\'', text)

用文字文本\'替换所有单引号。


把它们放在一起,你的 Perl 替换写得更好:

$text =~ s/'/'/g;

你的 Python 替换写得更好:

re.sub(r"'", r''', text)

  1. Python 2、Python 3 和当前版本的 Perl 如果非转义大括号不是量词的一部分,则将它们视为文字大括号。但是,这将是未来版本的 Perl 中的语法错误,并且最新版本的 Perl 会给出警告。

  2. 请参阅perlretutperlrere module 的 Python 文档。

【讨论】:

  • 附带说明,如果您尝试编码 HTML/XML 实体,您应该使用模块而不是编写一堆正则表达式。 Perl 有HTML::Entities 等;快速搜索 Python 2 出现 cgi.escape
  • 我认为使用 Python XML 转义也是一个好主意!但是对于这个任务来说太糟糕了,最好留着,因为后面有下游任务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-23
  • 2016-03-23
  • 1970-01-01
  • 2015-07-14
  • 2010-11-01
  • 2011-04-30
相关资源
最近更新 更多