正则表达式:匹配不在引号之间的单词

4
我希望能提供一个Python正则表达式,用于匹配给定的单词,但该单词不能在简单引号之间。我曾尝试使用“(?!...)”,但没有成功。
在下面的截图中,我想匹配除第四行外的所有“foe”。
此外,文本是作为一个大字符串给出的。
以下是链接regex101和示例文本:
var foe = 10;
foe = "";
dark_vador = 'bad guy'
foe = ' I\'m your father, foe ! '
bar = thingy + foe

1
发布你的尝试代码。 - Iron Fist
2
你能指定正则表达式101的真实链接,而不是屏幕截图吗? - RomanPerekhrest
3
请勿发布截图,应该在你的代码中进行编辑。 - user6613600
只需匹配单引号字符串(例如使用' [^ '\\] *(?:\\。[^ '\\] *)* ' ),然后匹配并捕获所需的单词。因此,整个过程看起来像是r"'[^'\\]*(?:\\.[^'\\]*)*'|(toto)"。然后,在re.sub中使用捕获(我猜测是在替换方法/ lambda表达式中)进行任何需要的操作。由于该文本看起来像一些代码,因此这种方法可能不起作用,因为注释可能包含不平衡的单引号。 - Wiktor Stribiżew
那么,你实际上在做什么?你打算怎样处理匹配的单词? - Wiktor Stribiżew
显示剩余8条评论
5个回答

5
下面的正则表达式解决方案在大多数情况下都有效,但如果不平衡的单引号出现在字符串字面值之外(例如在注释中),它可能会中断。
匹配字符串上下文的通常正则表达式技巧是匹配需要替换和匹配的内容并捕获您需要保留的内容。
以下是Python演示的示例:
import re
rx = r"('[^'\\]*(?:\\.[^'\\]*)*')|\b{0}\b"
s = r"""
    var foe = 10;
    foe = "";
    dark_vador = 'bad guy'
    foe = ' I\'m your father, foe ! '
    bar = thingy + foe"""
toReplace = "foe"
res = re.sub(rx.format(toReplace), lambda m: m.group(1) if m.group(1) else 'NEWORD', s)
print(res)

请查看Python演示

正则表达式应如下所示

('[^'\\]*(?:\\.[^'\\]*)*')|\bfoe\b

请查看正则表达式演示('[^'\\]*(?:\\.[^'\\]*)*')部分将单引号字符串文字捕获到第1组中,如果匹配,则将其放回结果中,而\bfoe\b匹配任何其他字符串上下文中的整个单词foe - 然后被替换为另一个单词。 注意:要匹配双引号字符串文字,请使用r"('[^'\\]*(?:\\.[^'\\]*)*'|\"[^\"\\]*(?:\\.[^\"\\]*)*\")"

3
你可以尝试这个:- ((?!\'[\w\s]*)foe(?![\w\s]*\'))

这个正则表达式在 ' I\'m your father, foe ! ' 中匹配到了 'foe'参考链接 - Cary Swoveland

2
这个正则表达式怎么样?this
>>> s = '''var foe = 10;
foe = "";
dark_vador = 'bad guy'
' I\m your father, foe ! '
bar = thingy + foe'''
>>>
>>> re.findall(r'(?!\'.*)foe(?!.*\')', s)
['foe', 'foe', 'foe']

这里的技巧是确保表达式不匹配任何带有前导和尾随'的字符串,并记得在此后的re表达式中考虑中间的字符,即.*

这不会奏效,因为在 foe = ' I'm your father, foe ! ' 中第一个敌人需要匹配 ='(。 - Liquiid
@Liquiid,你说,它不应该在单引号之间匹配吗?那为什么它还要匹配呢?... - Iron Fist
@Liquiid,您当前的声明与您最初的要求相矛盾。' I\m your father, foe ! '中的foe不应匹配,否则请详细说明您的问题。 - RomanPerekhrest
@RomanPerekhrest 我希望它可以监视所有不在引号之间的敌人。但是 -->foe<--= ' .... foe ...' 应该匹配。 - Liquiid
@Liquiid,请提供一个包含“foe”但不应匹配的字符串示例。 - Iron Fist
显示剩余2条评论

2

enter image description here

((?!\'[\w\s]*[\\']*[\w\s]*)foe(?![\w\s]*[\\']*[\w\s]*\'))

如果它在两个引号之间匹配到一个敌人,它就无法工作。 ='( - Liquiid
@Liquiid:别浪费时间看这些答案了。回顾先行断言也帮不了你。 - Wiktor Stribiżew

0
以下正则表达式的捕获组1将包含'foe'的匹配项。
r'^(?:[^'\n]|\\')*(?:(?<!\\)'(?:[^'\n]|\\')*(?:(?<!\\)')(?:[^'\n]|\\')*)*\b(foe)\b'

启动你的引擎!

Python的正则表达式引擎执行以下操作。

^           : assert beginning of string
(?:         : begin non-capture group
  [^'\n]    : match any char other than single quote and line terminator
  |         : or
  \\'       : match '\' then a single quote
)           : end non-capture group   
*           : execute non-capture group 0+ times
(?:         : begin non-capture group
  (?<!\\)   : next char is not preceded by '\' (negative lookbehind)
  '         : match single quote
  (?:       : begin non-capture group
    [^'\n]  : match any char other than single quote and line terminator
    |       : or
    \\'     : match '\' then a single quote
  )         : end non-capture group   
  *         : execute non-capture group 0+ times
  (?:       : begin non-capture group
    (?<!\\) : next char is not preceded by '\' (negative lookbehind)
    '       : match single quote
  )         : end non-capture group
  (?:       : begin non-capture group
    [^'\n]  : match any char other than single quote and line terminator
    |       : or
    \\'     : match '\' then a single quote
  )         : end non-capture group   
  *         : execute non-capture group 0+ times
)           : end non-capture group
*           : execute non-capture group 0+ times
\b(foe)\b   : match 'foe' in capture group 1

无法处理双引号“”和“foo +''+ bar”。 - pgp1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接