【问题标题】:How to use regex to replace a specific group in a string using Python?python - 如何使用正则表达式替换字符串中的特定组?
【发布时间】:2021-04-13 07:12:03
【问题描述】:

我想读入一个字符串并删除捕获的组(在本例中为“[^ ]+(&)[^ ])。

x = "apple&bob & john & smith" # original string
x = "applebob & john & smith" #after replacing string

这是我现在使用的代码。

import re

and_regex = re.compile(r'([^ ]+(&)[^ ])')
x = "apple&bob & john & smith"
x = re.sub(and_regex, " ",x)
print(x)

我不能使用字符串替换(string.replace),因为它会替换整个字符串中的“&”。

感谢您的帮助!

【问题讨论】:

  • 我想知道环顾四周是否会有所帮助:re.compile(r'(?<=\S)&(?=\S)').
  • &apple&bob & john & smith& 的预期是什么?

标签: python python-3.x regex string


【解决方案1】:

你可以这样做:

import re
x = "apple&bob & john & smith"
x = re.sub("(?<=\S)&(?=\S)", "",x)
print(x)

输出:

applebob & john & smith

【讨论】:

  • 正是我方法的补充;)。 Lookarounds 我总是要重新查找。所以我更喜欢没有环视的方法。 (懒惰;))。
  • 正如我们所看到的 - 没有环视,人们必须重复应用 re.sub() 来替换所有匹配项,只有环视一次 - 所以事后看来,这个解决方案更加优雅!
【解决方案2】:

作为替代方案,如果您还想删除开头的 &amp; 字符并以 &amp;apple&amp;bob &amp; john &amp; smith&amp; 结尾的字符,您可以在左侧声明一个非空白字符或在右侧声明一个非空白字符。

(?<=\S)&|&(?=\S)

Regex demo

import re

strings = [
    "apple&bob & john & smith",
    "&apple&bob & john & smith&",
    "&apple&bob & john & smith&&"
]

for s in strings:
    print(re.sub(r"(?<=\S)&|&(?=\S)", "", s))

输出

applebob & john & smith
applebob & john & smith
applebob & john & smith

【讨论】:

  • 这是最复杂的模式!
  • @Gwang-JinKim 谢谢,如果不需要左右两个非空白字符,这是一种替代方法。
【解决方案3】:

您可以捕获想要保留的部分。 而当替换为.sub() 方法时,输入 在替换字符串中使用\\1\\2 捕获部分。

import re
pattern = re.compile(r'(\S+)&(\S+)')
# `\S` means: any non-white character.
# see: https://docs.python.org/3/library/re.html

x = "apple&bob & john & smith"
x = pattern.sub("\\1\\2", x) # or also: re.sub(pattern, "\\1\\2", x)

x
## 'applebob & john & smith'

但是,这仅替换了 1 个出现,最左边的不重叠的一个,我们需要一个函数来替换字符串中的所有出现。可以使用递归来解决它:

def replace_all_pattern(pattern, s):
    if bool(re.match(pattern, s)):
        res = re.sub(pattern, "\\1\\2", s)
        return replace_all_pattern(pattern, res)
    else:
        return s


replace_all_pattern(r"(\S+)&(\S+)", "abble&bob&john&smith")
## 'abblebobjohnsmith'

但这在性能方面的效率低于使用环视。因此,仅当要替换一个匹配项时才使用此选项。在这种情况下,就性能而言,它比环视要好,但一旦出现不止一次并且必须检查:使用环视作为模式,因为它们会更有效。

【讨论】:

  • 此解决方案不适用于“apple&bob&john&smith”:它给出了“apple&bob&johnsmith”。
  • 啊,我明白了……它只做一次,而不是重复。
  • 但这是re.sub()的问题:“返回通过替换repl替换字符串中最左边不重叠出现的模式获得的字符串。”
  • 是的,问题在于“不重叠”。我认为您至少需要环顾四周。如果您将环视放在右侧,它应该比 2 环视更好,因为它们的成本很高(可能通过非线性解析完成),尤其是前瞻。
  • 是的,有了它们,它会给出“applebobjohnsmith”,因为环顾四周并不贪心(这使它们效率低下但也避免了重叠问题)
猜你喜欢
  • 1970-01-01
  • 2018-02-09
  • 2021-12-19
  • 2021-11-20
  • 2022-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-02
相关资源
最近更新 更多