Regex:用lookbehind替换连续组

gxwragnw  于 2023-08-08  发布在  其他
关注(0)|答案(2)|浏览(73)

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

input_string = "foo ab-123 ab-456"

字符串
我想通过用通用的东西替换每个ab-xxx组来清理它,但是 * 只有 * 整个字符串以“foo”开头。如果只有一个组,我可以这样做(在Python中):

pattern = re.sub(r"(?<=foo) (ab-\d{3})", "<ab-xxx>", input_string)


但是,我如何为所有群体做到这一点,并牢记积极的落后条件?

2hh7jdfx

2hh7jdfx1#

它必须是一个正则表达式吗?如果没有,您可以将任务分为两个步骤:

s = "foo ab-123 ab-456"
if s.startswith("foo"):
    s = re.sub(r"ab-\d{3}", "<ab-xxx>", s)

字符串
上面的例子给出了s = foo <ab-xxx> <ab-xxx>

nfs0ujit

nfs0ujit2#

如果你想让所有的事情都在一次调用中发生,你可以使用回调:

import re

def apply_masking(string):
  masked = re.sub(
    r'ab-\d{3}',
    lambda match: '<ab-xxx>' if match.string.startswith('foo') else match[0],
    string
  )

  return masked

字符串
请注意,每次找到匹配时都会调用回调,这意味着它将多次检查条件。此外,这段代码并不完全可读,而"readability counts"。话虽如此,你可能想使用@Socowi建议的解决方案。
或者,如果你不介意使用第三方模块和/或相对复杂的正则表达式,你可以使用regex模块来实现其非固定宽度的lookbehind功能:

import regex

def apply_masking(string):
  masked = regex.sub(r'(?<=^foo.*)ab-\d{3}', '<ab-xxx>', string)

  return masked
(?<=^foo.*)    # Match                    but only if the whole string starts with "foo".
ab-\d{3}       #       "ab-" and 3 digits

的数据
on regex101.com(ECMAScript)
或者,如果您更喜欢PCRE的\K\G

(?:            # Match either
  ^foo         # "foo" at the start of the string
|              # or
  \G(?!^)      # the position at the end of the previous match
)              # followed by
.*?            # anything, as few as possible,
\K             # (all of which we forfeit entirely)
ab-\d{3}       # then "ab-" and 3 digits.


on regex101.com(PCRE2)

相关问题