python、正则表达式、负前瞻和捕获匹配的问题
我对正则表达式有问题,也许你可以帮我解决。My line变量包含我想要操作的这些类型的字符串(每个for循环一个字符串):python、正则表达式、负前瞻和捕获匹配的问题,python,regex,string,negative-lookahead,Python,Regex,String,Negative Lookahead,我对正则表达式有问题,也许你可以帮我解决。My line变量包含我想要操作的这些类型的字符串(每个for循环一个字符串): sip=“100.107.0.5”sp=“123”dip=“100.107.193.1”dp=“123”nat dip=“84.2.44.19” sip=“100.101.199.1”sp=“37690”dip=“100.107.0.4”dp=“80”nat dip=“100.107.0.4” 最简单的部分:当dip=和nat dip=后的引号中的值相等时,则完全删除子字符
sip=“100.107.0.5”sp=“123”dip=“100.107.193.1”dp=“123”nat dip=“84.2.44.19”
sip=“100.101.199.1”sp=“37690”dip=“100.107.0.4”dp=“80”nat dip=“100.107.0.4”
最简单的部分:当dip=和nat dip=后的引号中的值相等时,则完全删除子字符串nat dip=“…”。这很容易做到:
line=re.sub(r'dip=“([^”]+)(“+)nat dip=“\1”,r'dip=“\1\2',line)
但可怕的是:当值不相等时,就写nat dip=的值代替dip=的值。我尝试了反向前瞻和捕获值,但它不断失败,我无法找出代码行的错误部分,即:
line=re.sub(r'dip=“([^“]+)(”+(“+)(!nat dip=“(\1)”),r'dip=“\3\2',line)
我得到的只是这个:
sip=“100.107.0.5”sp=“123”dip=”“dp=“123”nat dip=“84.2.44.19”
。。。与此相反:
sip=“100.107.0.5”sp=“123”dip=“84.2.44.19”dp=“123”
我做错了什么?你有什么建议吗 如果在这两种情况下都要删除
nat-dip
,可以在一次替换中使用这样的表达式()
dip=\"[^\"]*\"([ ]dp=\"[^\"]*\")[ ]nat-dip=\"([^\"]*)\"
Replace Pattern: dip="\2"\1
\2 contains the value of nat-dip,
\1 contains the dp attribute and its value since it's caught in the capture
dip=\" # Literal dip="
[^\"]* # Any character but ", zero or more times.
\" # Literal "
( # Open Capture Group 1 (to retain dp)
[ ] # a single space, bracketed here for visibility
dp=\" # Literal dp="
[^\"]* # Any character but ", zero or more times.
\" # Literal "
) # Close Capture group
[ ] # A single space
nat-dip=\" # Literal nat-dip="
( # Open capture group 2 (the value of nat-dip)
[^\"]* # Any character but ", zero or more times.
) # Close capture group 2
\" # Literal "
它总是将dip的值设置为nat dip的值。当它们相等时,这并没有明显的变化。当它们不相等时,它会更改值。在这两种情况下,它都会降低nat dip
更新:根据您的评论。你有可能会过来说“不,我们需要让nat在这种情况下保持冷静。”。理想情况下,我会使用分支重置(使捕获组保持一致,但Python不支持) 所以我会使用if-then-else条件,比如
(?(=环视条件)true模式| false模式))
。所有在线内容都说python支持这样的组,但regex101不断抛出一个模式错误(即使使用示例中的复制粘贴,也不会出现打字错误)。在这个演示中,我切换到PCRE
主要区别在于else-do没有捕获它的内容。它可以,但它永远不会使用它们
如果满足条件,则\3
包含整个nat dip
属性和值。如果不满足该条件,\3
为零,“
您会注意到替换模式是dip=“\4\5”\2\3
,因为nat dip值是否在\4
中且\5
是否为空取决于是否满足条件
在分支重置的情况下,两个值都可以与\4对齐。对眼睛来说会容易一点。没有任何正则表达式支持所有的好东西
但事实是,我只是向你展示了一个前瞻性的解决方案,因为你问,在这种情况下,甚至没有必要这样做。简单的替换就可以了,尽管有必要颠倒替换的顺序(),但在某些情况下,条件是救命稻草(特别是关于lookbehind)
最后,在更多的代码行中很难做到这一点。我们可以将其分解为使用python的if
返回结果的回调的模式提取,但我们的目标是提高效率。当然,不是所有的事情都可以用一个表达式完成。如果您想用dp
做其他事情,那么通常需要并且通常是有意义的单独操作。您正在处理html/xml吗?否。原始文本。逐行处理line@zweiund40当值不匹配时,dip的值应该设置为nat dip。那么nat dip也应该被删除吗?呃…是的。有时人们无法看到森林中的树木。最终,这是相同的,你的解决方案是tion更优雅,因为它简单。但是,出于好奇。用消极的前瞻和价值的捕获进行替换看起来会是什么样子。过去我有时会遇到这样的问题,我总是需要不止一行代码来解决它。有没有一种方法可以按照要求来做?@zweiund40是的,我完全明白这里的情况。陷得太深了,以至于你想得太多了,在正则表达式中可能会被淹没。///而且,用其他方法更新了答案。嗯……比我想象的要复杂得多。它看起来很棒,但我不得不承认我不完全理解它。我会掌握我的正则表达式预订并返回实验室。非常感谢。什么是投票?
dip=\"([^\"]*)\"([ ]dp=\"[^\"]*\")(?(?![ ]nat-dip="\1")([ ]nat-dip=\"([^\"]*)\")|[ ]nat-dip=\"([^\"]*)\")
dip=\"([^\"]*)\"([ ]dp=\"[^\"]*\")
(? # if
(?![ ]nat-dip="\1") # condition
([ ]nat-dip=\"([^\"]*)\") # then do
| # else
[ ]nat-dip=\"([^\"]*)\" # do
) # end if