python、正则表达式、负前瞻和捕获匹配的问题

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=后的引号中的值相等时,则完全删除子字符

我对正则表达式有问题,也许你可以帮我解决。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=后的引号中的值相等时,则完全删除子字符串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