【问题标题】:Remove duplicates keeping the last occurrence删除重复项,保留最后一次出现
【发布时间】:2021-11-07 19:11:39
【问题描述】:

鉴于这个草垛和Regex PCRE2(PHP>=7.3)

#1       #2      #3
green          [foo] [foo1]
red             [foo]
blue                  [foo] [foo1] [foo2]
yellow             [foo2]
green          [foo]
green          [foo] [foo1]
red             [foo]
pink                  [foo3]

地点:

#1 始终是一个可以包含数字但不能包含空格的字符串。

#2 始终是#13 之间的随机空间量。

#3#1 相同,但在括号内[ ],可以存在多个括号。

我正在尝试删除 #1 上所有包含欺骗的行,但保留找到的最后一个欺骗行。

看起来像:

blue                  [foo] [foo1] [foo2]
yellow             [foo2]
green          [foo] [foo1]
red             [foo]
pink                  [foo3]

清除#1 上所有包含相同字符串的行,只保留最后一个。

以及#1 上不包含欺骗的行例如:

pink [foo3] 保留它们。

我试图尽可能详细地解释它,如果它仍然不清楚或者使用正则表达式是不可能的,请告诉我。

【问题讨论】:

    标签: regex


    【解决方案1】:

    您可以将以下正则表达式(带有标志gmi)的匹配项转换为空字符串:

    ^([a-z\d]).*\n(?![\s\S]*\b^\1\b)
    

    标志 g 防止在第一次匹配后返回,m (multiline) 导致 ^$ 匹配行的开头和结尾,而不是开头和结尾字符串,i 使匹配不区分大小写。

    Demo

    表达式的元素如下:

    ^             # match beginning of line
    ([a-z\d])     # match one or more letters or digits and save to capture group 1
    .*            # match zero or more characters other than newlines
    \n            # match linefeed
    (?!           # begin negative lookahead
      [\s\S]*     # match zero or more characters including line terminators
      \b^\1\b     # match content of group 1 with word breaks before and after
    )             # end negative lookahead
    

    请注意,. 匹配回车符 \r。如果最后一行可能没有以换行符结束,请将\n 更改为(?:\n|$)


    如果您希望识别任何不具备所需格式的字符串,您可以使用以下正则表达式来匹配格式不正确的行:

    ^(?![a-z\d]*(?: *\[[^[\]\r\n]*\])+\r?\n).*
    

    Demo

    将光标悬停在链接中表达式的每个元素上,以获得对该元素功能的解释。

    【讨论】:

      【解决方案2】:

      你可以使用

      ^(\S+)\h+\[\S*\](?!\S).*$(?![\s\S]*^\1)
      
      • ^ 字符串开始
      • (\S+) 捕获第 1 组
      • \h+匹配1+个空格
      • \[\S*\](?!\S) 从开头匹配 [ 直到关闭 ] 并断言右侧的空白边界不匹配 [foo]a
      • .*$ 匹配该行的其余部分
      • (?![\s\S]*^\1) 负前瞻,断言捕获组 1 不再出现在文本中

      查看regex demo | PHP demo.

      例如

      $re = '/^(\S+)\h+\[\S*\](?!\S).*$(?![\s\S]*^\1)/m';
      $str = 'green          [foo] [foo1]
      red             [foo]
      blue                  [foo] [foo1] [foo2]
      yellow             [foo2]
      green          [foo]
      green          [foo] [foo1]
      red             [foo]
      pink                  [foo3]';
      
      preg_match_all($re, $str, $matches);
      print_r($matches[0]);
      

      输出

      Array
      (
          [0] => blue                  [foo] [foo1] [foo2]
          [1] => yellow             [foo2]
          [2] => green          [foo] [foo1]
          [3] => red             [foo]
          [4] => pink                  [foo3]
      )
      

      【讨论】:

        猜你喜欢
        • 2022-11-19
        • 1970-01-01
        • 2016-10-11
        • 2016-09-10
        • 1970-01-01
        • 2020-12-18
        • 2022-07-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多