如何写python re.sub pattern 忽略单引号或双引号?
how write python re.sub pattern Ignore single or double quotes?
mystr = """{abc} [abc] (abc) ['abc'] ["abc"]"""
pattern = r'\babc\b'
mystr = re.sub(pattern, "nnn", mystr)
print(mystr)
# {nnn} [nnn] (nnn) ['nnn'] ["nnn"]
但是,我希望 return {nnn} [nnn] (nnn) ['abc'] ["abc"]
如何忽略单引号或双引号?
您可以使用正则表达式模式,该模式仅在大括号、方括号或圆括号内精确定位 abc
:
mystr = """{abc} [abc] (abc) ['abc'] ["abc"]"""
output = re.sub(r'([{(\[])abc([})\]])', r'nnn', mystr)
print(output) # {nnn} [nnn] (nnn) ['abc'] ["abc"]
对于仅针对元素 not 引用的更通用的解决方案,然后将 re.sub
与回调函数一起使用:
mystr = """{abc} [abc] (abc) ['abc'] ["abc"]"""
output = re.sub(r'([{(\[])(.*?)([})\]])', lambda m: m.group(1) + 'nnn' + m.group(3) if not re.search(r"^['\"].*['\"]$", m.group(2)) else m.group(), mystr)
print(output) # {nnn} [nnn] (nnn) ['abc'] ["abc"]
如果您想要一个简单的解决方案来替换 abc
由引号以外的任何 non-word 字符界定,您可以将 pattern
更改为:
pattern = r'[^\w\'\"]abc[^w\'\"]'
您可以通过将单词边界与环视相结合来忽略单引号或双引号,以断言左侧不是单引号或双引号 (?<![\'"])
并且右侧不是单引号或双引号 (?![\'"])
例子
mystr = """{abc} [abc] (abc) ['abc'] ["abc"]"""
output = re.sub(r'\b(?<![\'"])abc\b(?![\'"])', r'nnn', mystr)
print(output)
输出
{nnn} [nnn] (nnn) ['abc'] ["abc"]
如果你想用相同的引号配对相同的左括号和右括号,你可以使用带有交替、捕获组和反向引用的模式来首先匹配你不想替换的内容。
最后一个alternative有capture group 4,包含了你最终想要替换的东西,你可以在re.sub的回调中检查group 4。
import re
pattern = r"{([\"'])[^{}]*}|\[([\"'])[^][]*]|\(([\"'])[^()]*\)|((?<={)[^{}]*(?=})|(?<=\()[^()]*(?=\))|(?<=\[)[^][]*(?=]))"
s = ("{abc} [abc] (abc) ['abc'] [\"abc\"]\n"
"{\"abc\"} ('abc')(\"abc\")\n"
"{abc](\"abc\"}{'abc\"}")
result = re.sub(pattern, lambda m: 'nnn' if m.group(4) else m.group(), s)
print(result)
输出
{nnn} [nnn] (nnn) ['abc'] ["abc"]
{"abc"} ('abc')("abc")
{nnn}{nnn}
看到一个regex101 demo for all the matches and a Python demo.
mystr = """{abc} [abc] (abc) ['abc'] ["abc"]"""
pattern = r'\babc\b'
mystr = re.sub(pattern, "nnn", mystr)
print(mystr)
# {nnn} [nnn] (nnn) ['nnn'] ["nnn"]
但是,我希望 return {nnn} [nnn] (nnn) ['abc'] ["abc"]
如何忽略单引号或双引号?
您可以使用正则表达式模式,该模式仅在大括号、方括号或圆括号内精确定位 abc
:
mystr = """{abc} [abc] (abc) ['abc'] ["abc"]"""
output = re.sub(r'([{(\[])abc([})\]])', r'nnn', mystr)
print(output) # {nnn} [nnn] (nnn) ['abc'] ["abc"]
对于仅针对元素 not 引用的更通用的解决方案,然后将 re.sub
与回调函数一起使用:
mystr = """{abc} [abc] (abc) ['abc'] ["abc"]"""
output = re.sub(r'([{(\[])(.*?)([})\]])', lambda m: m.group(1) + 'nnn' + m.group(3) if not re.search(r"^['\"].*['\"]$", m.group(2)) else m.group(), mystr)
print(output) # {nnn} [nnn] (nnn) ['abc'] ["abc"]
如果您想要一个简单的解决方案来替换 abc
由引号以外的任何 non-word 字符界定,您可以将 pattern
更改为:
pattern = r'[^\w\'\"]abc[^w\'\"]'
您可以通过将单词边界与环视相结合来忽略单引号或双引号,以断言左侧不是单引号或双引号 (?<![\'"])
并且右侧不是单引号或双引号 (?![\'"])
例子
mystr = """{abc} [abc] (abc) ['abc'] ["abc"]"""
output = re.sub(r'\b(?<![\'"])abc\b(?![\'"])', r'nnn', mystr)
print(output)
输出
{nnn} [nnn] (nnn) ['abc'] ["abc"]
如果你想用相同的引号配对相同的左括号和右括号,你可以使用带有交替、捕获组和反向引用的模式来首先匹配你不想替换的内容。
最后一个alternative有capture group 4,包含了你最终想要替换的东西,你可以在re.sub的回调中检查group 4。
import re
pattern = r"{([\"'])[^{}]*}|\[([\"'])[^][]*]|\(([\"'])[^()]*\)|((?<={)[^{}]*(?=})|(?<=\()[^()]*(?=\))|(?<=\[)[^][]*(?=]))"
s = ("{abc} [abc] (abc) ['abc'] [\"abc\"]\n"
"{\"abc\"} ('abc')(\"abc\")\n"
"{abc](\"abc\"}{'abc\"}")
result = re.sub(pattern, lambda m: 'nnn' if m.group(4) else m.group(), s)
print(result)
输出
{nnn} [nnn] (nnn) ['abc'] ["abc"]
{"abc"} ('abc')("abc")
{nnn}{nnn}
看到一个regex101 demo for all the matches and a Python demo.