【问题标题】:Replace strings in a string by a substring of those strings用这些字符串的子字符串替换字符串中的字符串
【发布时间】:2017-12-06 14:08:22
【问题描述】:

假设我有一个这样的字符串:

s = '(X_xy09 and X_foobar or (X_abc123 and X_something))'

我想把它变成

'(xy09 and foobar or (abc123 and something))'

那么 - 在这种特殊情况下 - 我可以简单地做

s.replace('X_', "")

它给出了所需的输出。

但是,在我的实际数据中,可能不仅有X_,还有其他前缀,所以上面的replace语句不起作用。

我需要的是替换

一个大写字母后跟一个下划线和任意的字母和数字序列

通过

第一个下划线之后的所有内容。

所以,要提取我可以使用的所需元素:

import re
print(re.findall('[A-Z]{1}_[a-zA-Z0-9]+', s))

打印出来的

['X_xy09', 'X_foobar', 'X_abc123', 'X_something']

我现在如何替换这些元素以便获得

'(xy09 and foobar or (abc123 and something))'

?

【问题讨论】:

  • 尝试使用re.sub
  • @WiktorStribiżew:很想,但不知道如何在这种情况下使用它。如果您知道如何,请随时将其发布为答案... :)
  • 试试ideone.com/Qs9ldO。模式的确切标准是什么?它应该以单词边界开头还是仅在( 之后?
  • @WiktorStribiżew:啊,反向引用!太好了,解决了。请将其发布为答案,然后我赞成并接受。模式就像描述的那样简单:大写字母、下划线、一些任意的东西。并不总是有( 参与。
  • re.sub(r'[A-Z]_(?=[a-zA-Z0-9])', '', s)

标签: python regex string replace


【解决方案1】:

如果您需要删除后面带有下划线的大写 ASCII 字母,只有在前面没有单词 char 并且后跟字母数字 char 时,才可以使用

import re
s = '(X_xy09 and X_foobar or (X_abc123 and X_something))'
print(re.sub(r'\b[A-Z]_([a-zA-Z0-9])', r'\1', s))

查看Python demoregex demo

模式详情

  • \b - 前导词边界
  • [A-Z]_ - ASCII 大写字母和_
  • ([a-zA-Z0-9]) - 第 1 组(后来在替换模式中用 \1 引用):1 个字母数字字符。

【讨论】:

  • 注意等于re.sub(r'\b[A-Z]_(?=[a-zA-Z0-9])', '', s)
【解决方案2】:

如果只需要替换大写字母后跟下划线,可以使用正则表达式r'[A-Z]_'

s = '(X_xy09 and X_foobar or (X_abc123 and X_something))'
re.sub(r'[A-Z]_', '', s)

如果您有其他未提及的标准,您可能需要添加。 (例如,您的一些目标值遵循单词边界,而另一些则遵循括号。)如果您的输入类似于XY_something,则上述内容可能会给您错误的输出。这取决于您期望的输出。

【讨论】:

  • 不错的解决方案。
【解决方案3】:

另一个re.sub() 方法:

import re

s = '(X_xy09 and X_foobar or (X_abc123 and X_something))'
result = re.sub(r'[A-Z]_(?=[a-zA-Z0-9]+)', '', s)

print(result)

输出:

(xy09 and foobar or (abc123 and something))

  • [A-Z]_(?=[a-zA-Z0-9]+) - (?=...) 正向前瞻断言,确保替换的 [A-Z]_ 子字符串后跟字母数字序列 [a-zA-Z0-9]+

【讨论】:

  • 工作正常。 ?= 部分是干什么用的?
  • @Cleb,这是积极的前瞻断言,请参阅我的解释
【解决方案4】:

您可以将re.sub() 与前瞻断言一起使用:

>>> import re
>>> s = '(X_xy09 and X_foobar or (X_abc123 and X_something))'
>>> re.sub(r'\b[A-Z]_(?=[a-zA-Z0-9])', '', s)
'(xy09 and foobar or (abc123 and something))'

来自docs

(?=...)
如果 ... 匹配下一个则匹配,但不使用任何字符串。这称为前瞻断言。例如,Isaac (?=Asimov) 将匹配 'Isaac ',前提是它后面跟着 'Asimov'

【讨论】:

  • 似乎与 RomanPerekhrest 的回答相同,但仍然值得一票... :)
猜你喜欢
  • 2017-03-23
  • 2012-04-03
  • 2013-07-23
  • 2017-04-24
  • 2016-11-28
相关资源
最近更新 更多