模式意外结束:Python正则表达式

模式意外结束:Python正则表达式,python,regex,pattern-matching,Python,Regex,Pattern Matching,当我使用下面的python正则表达式来执行下面描述的功能时,我得到了一个错误:模式的意外结束 Regex: modified=re.sub(r'^(?i)((?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?)(?-i) (CODE[0-9]{3})(?!</a>)',r'<a href="http://productcode/\g<1>">\g<1></a>',input) CODE8

当我使用下面的python正则表达式来执行下面描述的功能时,我得到了一个错误:模式的意外结束

Regex:

modified=re.sub(r'^(?i)((?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?)(?-i)
(CODE[0-9]{3})(?!</a>)',r'<a href="http://productcode/\g<1>">\g<1></a>',input)
CODE876
CODE223
matchjustCODE657
CODE69743
code876
testing1CODE888
example2CODE098
http://replaced/CODE665
应匹配:

并将引用替换为

http://productcode/CODE876
http://productcode/CODE223
matchjusthttp://productcode/CODE657
http://productcode/CODE69743
不应匹配:

code876
testing1CODE888
testing2CODE776
example3CODE654
example2CODE098
http://replaced/CODE665
最终输出

http://productcode/CODE876
http://productcode/CODE223
matchjusthttp://productcode/CODE657
http://productcode/CODE69743
code876
testing1CODE888
example2CODE098
http://replaced/CODE665
CODE123 CODE765 testing1CODE123 example1CODE345 http://www.coding.com/CODE333 CODE345

CODE234

CODE333
<a href="http://productcode/CODE123">CODE123</a> <a href="http://productcode/CODE765">CODE765</a> testing1<a href="http://productcode/CODE123">CODE123</a> example1<a href="http://productcode/CODE345">CODE345</a> http://www.coding.com/<a href="http://productcode/CODE333">CODE333</a> <a href="http://productcode/CODE345">CODE345</a>

<a href="http://productcode/CODE234">CODE234</a>

<a href="http://productcode/CODE333">CODE333</a>
编辑和更新1

modified=re.sub(r'^(?i)((?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?)(CODE[0-9]{3})(?!</a>)',r'<a href="http://productcode/\g<1>">\g<1></a>',input)
输出

http://productcode/CODE876
http://productcode/CODE223
matchjusthttp://productcode/CODE657
http://productcode/CODE69743
code876
testing1CODE888
example2CODE098
http://replaced/CODE665
CODE123 CODE765 testing1CODE123 example1CODE345 http://www.coding.com/CODE333 CODE345

CODE234

CODE333
<a href="http://productcode/CODE123">CODE123</a> <a href="http://productcode/CODE765">CODE765</a> testing1<a href="http://productcode/CODE123">CODE123</a> example1<a href="http://productcode/CODE345">CODE345</a> http://www.coding.com/<a href="http://productcode/CODE333">CODE333</a> <a href="http://productcode/CODE345">CODE345</a>

<a href="http://productcode/CODE234">CODE234</a>

<a href="http://productcode/CODE333">CODE333</a>
测试1示例1http://www.coding.com/ 
正则表达式适用于原始输入,但不适用于文本文件中的字符串输入


有关更多结果,请参见输入4和5

我看到的唯一问题是使用错误的捕获组进行替换

modified=re.sub(r'^(?i)((?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?)(?-i)(CODE[0-9]{3})(?!</a>)',r'<a href="http://productcode/\g<1>">\g<1></a>',input)  
                       ^                                                        ^                                                        ^
                    first capturing group                                  second one                                         using the first group
modified=re.sub(r'^(?i)((?:(!http:/)(?!testing[0-9])(?!example[0-9])*?)(?-i)(代码[0-9]{3})(?!)”,r'',输入)
^                                                        ^                                                        ^
第一捕获组使用第一组的第二捕获组
在这里,我让第一个也是一个非捕获组

^(?i)(?:(?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?)(?-i)(CODE[0-9]{3})(?!</a>)
^(?i)(?:(?:(?!http:/)(?!测试[0-9])(?!示例[0-9])*?)(?-i)(代码[0-9]{3})(?!)

查看它

我看到的唯一问题是您使用了错误的捕获组进行替换

modified=re.sub(r'^(?i)((?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?)(?-i)(CODE[0-9]{3})(?!</a>)',r'<a href="http://productcode/\g<1>">\g<1></a>',input)  
                       ^                                                        ^                                                        ^
                    first capturing group                                  second one                                         using the first group
modified=re.sub(r'^(?i)((?:(!http:/)(?!testing[0-9])(?!example[0-9])*?)(?-i)(代码[0-9]{3})(?!)”,r'',输入)
^                                                        ^                                                        ^
第一捕获组使用第一组的第二捕获组
在这里,我让第一个也是一个非捕获组

^(?i)(?:(?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?)(?-i)(CODE[0-9]{3})(?!</a>)
^(?i)(?:(?:(?!http:/)(?!测试[0-9])(?!示例[0-9])*?)(?-i)(代码[0-9]{3})(?!)

你看

好吧,看起来问题出在
(?-i)
,这让人惊讶。内联修饰符语法的目的是让您将修饰符应用于正则表达式的选定部分。至少在大多数口味中都是这样。在Python中,它们似乎总是修改整个正则表达式,就像外部标志一样(
re.I
re.M
,等等)。备选的
(?i:xyz)
语法也不起作用

另一方面,我不认为有任何理由使用三个单独的lookahead,就像您在这里所做的那样:

(?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?
仅仅是或是把它们放在一起:

(?:(?!http://|testing[0-9]|example[0-9]).)*?

编辑:我们似乎已经从为什么正则表达式抛出异常的问题转移到了为什么它不工作的问题。我不确定我是否理解您的要求,但下面的正则表达式和替换字符串返回您想要的结果

s1 = re.sub(r'^((?!http://|testing[0-9]|example[0-9]).*?)(CODE[0-9]{3})(?!</a>)', 
            r'\g<1><a href="http://productcode/\g<2>">\g<2></a>', s)
诀窍是使用函数代替静态字符串进行替换。每当正则表达式与锚元素匹配时,函数都会在组(1)中找到它,并返回不变的结果。否则,它将使用组(2)和组(3)来构建一个新的组


(我知道这是一个可怕的代码,但我现在太累了,无法学习更具Python风格的方法。)

好吧,看起来问题在于
(?-I)
,这令人惊讶。内联修饰符语法的目的是让您将修饰符应用于正则表达式的选定部分。至少在大多数口味中都是这样。在Python中,它们似乎总是修改整个正则表达式,就像外部标志一样(
re.I
re.M
,等等)。备选的
(?i:xyz)
语法也不起作用

另一方面,我不认为有任何理由使用三个单独的lookahead,就像您在这里所做的那样:

(?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?
仅仅是或是把它们放在一起:

(?:(?!http://|testing[0-9]|example[0-9]).)*?

编辑:我们似乎已经从为什么正则表达式抛出异常的问题转移到了为什么它不工作的问题。我不确定我是否理解您的要求,但下面的正则表达式和替换字符串返回您想要的结果

s1 = re.sub(r'^((?!http://|testing[0-9]|example[0-9]).*?)(CODE[0-9]{3})(?!</a>)', 
            r'\g<1><a href="http://productcode/\g<2>">\g<2></a>', s)
诀窍是使用函数代替静态字符串进行替换。每当正则表达式与锚元素匹配时,函数都会在组(1)中找到它,并返回不变的结果。否则,它将使用组(2)和组(3)来构建一个新的组


(我知道这是一段可怕的代码,但我现在太累了,无法学习更具python风格的方法。)

对于复杂正则表达式,使用来记录您正在做的事情,并确保括号正确匹配(即使用缩进来指示当前嵌套级别)。

对于复杂正则表达式,使用文档记录您正在做的事情,并确保括号正确匹配(即使用缩进指示当前嵌套级别)。

您的主要问题是
(?-i)
这对于Python 2.7和3.2来说是一厢情愿的想法。有关更多详细信息,请参阅下文

import re
# modified=re.sub(r'^(?i)((?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?)(?-i)
# (CODE[0-9]{3})(?!</a>)',r'<a href="http://productcode/\g<1>">\g<1></a>',input)
# observation 1: as presented, pattern has a line break in the middle, just after (?-i)
# ob 2: rather hard to read, should use re.VERBOSE
# ob 3: not obvious whether it's a complile-time or run-time problem
# ob 4: (?i) should be at the very start of the pattern (see docs)
# ob 5: what on earth is (?-i) ... not in 2.7 docs, not in 3.2 docs
pattern = r'^(?i)((?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?)(?-i)(CODE[0-9]{3})(?!</a>)'
#### rx = re.compile(pattern)
# above line failed with "sre_constants.error: unexpected end of pattern"
# try without the (?-i)
pattern2 = r'^(?i)((?:(?!http://)(?!testing[0-9])(?!example[0-9]).)*?)(CODE[0-9]{3})(?!</a>)'
rx = re.compile(pattern2)
# This works, now you need to work on observations 1 to 4,
# and rethink your CODE/code strategy
重新导入
#modified=re.sub(r'^(?i)((?:(!http:/)(?!testing[0-9])(?!example[0-9])*?)(?-i)
#(代码[0-9]{3})(?!)',r',输入)
观察1:如图所示,模式在中间有一个直线断裂,在(-i)之后。
#ob 2:很难阅读,应该使用re.VERBOSE
#ob 3:这是复杂时间还是运行时问题并不明显
#ob 4:(?i)应该在模式的最开始(见文档)
#ob 5:到底什么是(?-i)。。。不在2.7文档中,不在3.2文档中
pattern=r'^(?i)((?:(?!http:/)(?!testing[0-9])(?!example[0-9])*?)(?-i)(代码[0-9]{3})(?!)
####rx=重新编译(模式)
#上述行失败,出现“sre_常量。错误:模式意外结束”
#尝试不使用(?-i)
模式2=r'^(?i)((?:(?!http:/)(?!测试[0-9])(?!示例[0-9]))*?(代码[0-9]{3})(?!)
rx=重新编译(模式2)
#这是可行的,现在你需要处理观察值1到4,
#并重新思考您的代码/代码策略
看来建议被置若罔闻。。。以下是re.VERBOSE格式的模式:

pattern4 = r'''
    ^
    (?i)
    (
        (?:
            (?!http://)
            (?!testing[0-9])
            (?!example[0-9])
            . #### what is this for?
        )*?
    ) ##### end of capturing group 1
    (CODE[0-9]{3}) #### not in capturing group 1
    (?!</a>)
    '''
pattern4=r''
^
(?一)
(
(?:
(?!http://)
(?!测试[0-9])
(?!示例[0-9])
这是什么