当前位置: 首页 > 知识库问答 >
问题:

替换中的Python Regex转义运算符\

百里弘致
2023-03-14

我不理解python正则表达式中scape操作符\与原始字符串的r'一起工作的逻辑。谢谢你的帮助。

代码:

import re
text=' esto  .es  10  . er - 12 .23 with [  and.Other ] here is more ; puntuation'
print('text0=',text)
text1 = re.sub(r'(\s+)([;:\.\-])', r'\2', text)
text2 = re.sub(r'\s+\.', '\.', text)
text3 = re.sub(r'\s+\.', r'\.', text)
print('text1=',text1)
print('text2=',text2)
print('text3=',text3)

该理论认为:反斜杠字符(“\”)表示特殊形式或允许使用特殊字符而不调用其特殊含义。

正如问题末尾提供的链接所解释的,r'代表原始字符串,也就是说,符号没有特殊意义,它就是这样。

所以在上面的正则表达式中,我希望text2和text3是不同的,因为替换文本是“.”在文本2中,即一个句点,而(原则上)文本3中的替换文本为r''这是一个原始字符串,即应该显示的字符串、反斜杠和句点。但它们的结果是一样的:

结果是:

text0=  esto  .es  10  . er - 12 .23 with [  and.Other ] here is more ; puntuation
text1=  esto.es  10. er- 12.23 with [  and.Other ] here is more; puntuation
text2=  esto\.es  10\. er - 12\.23 with [  and.Other ] here is more ; puntuation
text3=  esto\.es  10\. er - 12\.23 with [  and.Other ] here is more ; puntuation
#text2=text3 but substitutions are not the same r'\.' vs '\.'

在我看来,r'在替换部分和反斜杠中的工作方式不同。另一方面,我的直觉告诉我,我遗漏了一些东西。

编辑1:以下@Wiktor Stribi的评论。他指出(点击链接):

import re
print(re.sub(r'(.)(.)(.)(.)(.)(.)', 'a\6b', '123456'))
print(re.sub(r'(.)(.)(.)(.)(.)(.)', r'a\6b', '123456'))
# in my example the substitutions were not the same and the result were equal
# here indeed r' changes the results

其中:

ab
a6b

这让我更加困惑。

注意:我读过这个关于原始字符串的堆栈溢出问题,它是超级完整的。然而,它并没有提到替代

共有3个答案

谢璞
2023-03-14

解决所有这些字符串转义问题的一种简单方法是使用函数/lambda作为repl参数,而不是字符串。例如:

output = re.sub(
    pattern=find_pattern,
    repl=lambda _: replacement,
    string=input,
)

替换字符串根本不会被解析,只是被替换来代替匹配。

景光赫
2023-03-14

从文件(我的重点):

重新。sub(pattern,repl,string,count=0,flags=0)返回通过替换repl替换string中pattern的最左侧非重叠出现而获得的字符串。如果找不到模式,则返回的字符串将保持不变。repl可以是字符串或函数;如果它是字符串,则会处理其中的任何反斜杠转义。即,\n转换为单个换行符,\r转换为回车符,依此类推。ASCII字母的未知转义保留供将来使用,并作为错误处理。其他未知的逃逸行为,如\

repl参数不仅仅是纯文本。它也可以是函数名或组中的位置(例如\g

此外,从这里:

与标准C不同,所有无法识别的转义序列在字符串中保持不变,即反斜杠留在结果中。

开始不是特殊的转义字符,“\”r'\'相同\

凌华奥
2023-03-14

首先,,

replacement patterns ≠ regular expression patterns

我们使用正则表达式模式来搜索匹配项,我们使用替换模式来替换正则表达式找到的匹配项。

注意:替换模式中唯一的特殊字符是反斜杠,\。只有反斜杠必须加倍。

Python中的替换模式语法

re。sub文档令人困惑,因为它们提到了可用于替换模式(如\n\r)和正则表达式转义序列(\6)的字符串转义序列,以及可同时用作正则表达式和字符串转义序列(\

我使用术语regex转义序列来表示一个转义序列,该转义序列由一个反斜杠字符组成,即,\\\X'r'\X',一个字符串转义序列来表示一个\序列和一个字符或一些共同构成有效字符串转义序列的序列。它们只能在常规字符串文本中识别。在原始字符串文字中,只能转义(这就是为什么不能用\”结束原始字符串文字,但齿隙仍然是字符串的一部分)。

因此,在替换模式中,您可以使用反向引用:

re.sub(r'\D(\d)\D', r'\1', 'a1b')    # => 1
re.sub(r'\D(\d)\D', '\\1', 'a1b')    # => 1
re.sub(r'\D(\d)\D', '\g<1>', 'a1b')  # => 1
re.sub(r'\D(\d)\D', r'\g<1>', 'a1b') # => 1

您可能会看到r'\1''\\1'是相同的替换模式,\1。如果使用'\1',它将被解析为字符串转义序列,一个具有八进制值001的字符。如果您忘记使用带有明确反向引用的r前缀,则不会有问题,因为\g不是有效的字符串转义序列,因此,\转义字符保留在字符串中。阅读我链接到的文档:

与标准C不同,所有无法识别的转义序列在字符串中保持不变,即反斜杠留在结果中。

所以,当您传递'\.'作为替换字符串时,您实际上发送了\。双字符组合作为替换字符串,这就是为什么您在结果中得到\。

\是Python替换模式中的一个特殊字符

如果您使用re。sub(r'\s\',r'\.',text),您将获得与text2text3案例相同的结果,请参见此演示。

这是因为两个文本反斜杠表示替换模式中的一个反斜杠。如果在正则表达式模式中没有第2组,但在替换中传递r'\2'以实际替换为\2字符组合,则会出现错误。

因此,当您有动态的、用户定义的替换模式时,您需要将替换模式中的所有反斜杠加倍,以作为文本字符串传递:

re.sub(some_regex, some_replacement.replace('\\', '\\\\'), input_string)

 类似资料:
  • 问题内容: 我发现Java编译对于使用int和float的赋值和自赋值语句具有非预期的行为。 以下代码块说明了该错误。 在自赋值中,编译不会发出错误,但是求和的结果是带有值的int ,并且变量保持值。 在表达式中,编译器会发出一条错误消息 “错误:可能丢失精度” 。 有人可以解释这种行为。 编辑:我已经将此代码块发布在https://compilr.com/cguedes/java-autoass

  • 我想使用方法发送POST请求,但是我的JSON有一些国际字符,比如surunn。 不幸的是,我的WebAPI在从格式解码这个字符串时遇到了一些问题:。 使用时,我的API可以很好地处理非转义字符串和unicode转义字符串:。 我尝试了此操作,但在将转换为unicode后,转义了: 我有两个反斜杠字符串: 我试图用一个反斜杠替换两个反斜杠,但没有成功: 我该如何替换它们?

  • 这是这个问题的后续问题。answers中提出的解决方案是使用groupBy运算符。这通常是好的,但正如其文档中所提到的,不建议与大量不同的键一起使用,比如说数以万计的键。 每个群体在本质上都有无限的元素,这些元素可能随时到达。此外,我需要限制并发处理的组的数量。据我所知,如果我使用上面的代码,要么我会达到开放组的隐式限制,新组不会被打开(处理),要么Ï最终会达到内存不足,因为即使是长时间不活动的组

  • 9.2.3 字符转义运算符 在引用宏时,如果实参中含有特殊字符,而又要该特殊字符当作普通字符来出来,那么,就必须在该特殊字符前加上字符转义运算符“!”。 下面不使用和使用字符转义运算符的宏引用语句及其宏扩展的结果: DEFMSG <Input one number(>90):> 1DB 'Input one number(90):', 0DH, 0AH, '$'  ;第一个“>”与字符“<”相比配

  • 下面的代码将泛型(POD)类型包装成(模板)类,并定义内部模板转换操作符,以便能够在兼容(但不同)类型之间进行隐式转换。我希望代码是相当自我解释的。在任何情况下,我都无法理解为什么将转换为另一个POD都能正常工作,但将(此处键入为)转换为)却失败得很 有什么想法吗?代码如下:

  • C++ 运算符 强制转换运算符是一种特殊的运算符,它把一种数据类型转换为另一种数据类型。强制转换运算符是一元运算符,它的优先级与其他一元运算符相同。 大多数的 C++ 编译器都支持大部分通用的强制转换运算符: (type) expression 其中,type 是转换后的数据类型。下面列出了 C++ 支持的其他几种强制转换运算符: const_cast<type> (expr): const

  • 问题内容: 我有一个Java应用程序,该应用程序大量使用大文件来读取,处理和传递给SolrEmbeddedServer(http://lucene.apache.org/solr/)。 其中一个功能可以进行基本的HTML转义: 在对应用程序进行性能分析时,程序在此功能上花费大约58%的时间,总共47%的时间用于替换,而11%的时间用于replaceAll。 现在,是用Java替换程序速度这么慢吗?