【问题标题】:'negative' pattern matching in pythonpython中的“否定”模式匹配
【发布时间】:2012-08-18 22:27:19
【问题描述】:

我有以下输入,

OK SYS 10 LEN 20 12 43
1233a.fdads.txt,23 /data/a11134/a.txt
3232b.ddsss.txt,32 /data/d13f11/b.txt
3452d.dsasa.txt,1234 /data/c13af4/f.txt
.

我想提取所有输入除了包含的行 “OK SYS 10 LEN 20”和包含单个"."(点)的最后一行。 也就是我要提取以下内容

1233a.fdads.txt,23 /data/a11134/a.txt
3232b.ddsss.txt,32 /data/d13f11/b.txt
3452d.dsasa.txt.1234 /data/c13af4/f.txt

我尝试了以下,

for item in output:
    matchObj = re.search("^(?!OK) | ^(?!\\.)", item)
    if matchObj:
        print "got item "  + item

但它不起作用,因为它不会产生任何输出。

【问题讨论】:

  • 是文件的第一个代码块行中的行吗?
  • 什么是 \\.为了?

标签: python regex


【解决方案1】:

in action:

matchObj = re.search("^(?!OK|\\.).*", item)

不要忘记将.* 放在否定前瞻之后,否则您将无法获得任何匹配;-)

【讨论】:

  • 负前瞻不匹配任何东西,它只是在 before 匹配前进行前瞻,并应用于其后的下一个模式(例如.*)我需要一段时间才能弄清楚。
【解决方案2】:

使用否定匹配。 (另请注意,默认情况下,正则表达式中的空格很重要,因此不要将内容隔开。或者,使用re.VERBOSE。)

for item in output:
    matchObj = re.search("^(OK|\\.)", item)
    if not matchObj:
        print "got item " + item

【讨论】:

    【解决方案3】:
     if not (line.startswith("OK ") or line.strip() == "."):
         print line
    

    【讨论】:

    • 您还需要处理.,但这很容易。
    • 谢谢,为了完整起见添加。
    【解决方案4】:

    你为什么不匹配 OK SYS 行而不返回它。

    for item in output:
        matchObj = re.search("(OK SYS|\\.).*", item)
        if not matchObj:
            print "got item "  + item
    

    【讨论】:

      【解决方案5】:

      如果这是一个文件,您可以直接跳过第一行和最后一行,然后使用csv 阅读其余部分:

      >>> s = """OK SYS 10 LEN 20 12 43
      ... 1233a.fdads.txt,23 /data/a11134/a.txt
      ... 3232b.ddsss.txt,32 /data/d13f11/b.txt
      ... 3452d.dsasa.txt,1234 /data/c13af4/f.txt
      ... ."""
      >>> stream = StringIO.StringIO(s)
      >>> rows = [row for row in csv.reader(stream,delimiter=',') if len(row) == 2]
      >>> rows
      [['1233a.fdads.txt', '23 /data/a11134/a.txt'], ['3232b.ddsss.txt', '32 /data/d13f11/b.txt'], ['3452d.dsasa.txt', '1234 /data/c13af4/f.txt']]
      

      如果它是一个文件,那么你可以这样做:

      with open('myfile.txt','r') as f:
         rows = [row for row in csv.reader(f,delimiter=',') if len(row) == 2]
      

      【讨论】:

        【解决方案6】:
        and(re.search("bla_bla_pattern", str_item, re.IGNORECASE) == None)
        

        正在工作。

        【讨论】:

          【解决方案7】:

          您也可以在没有负面展望的情况下做到这一点。您只需在要提取的表达式部分添加括号。这个带括号的结构被命名为group

          让我们编写python代码:

          string = """OK SYS 10 LEN 20 12 43
          1233a.fdads.txt,23 /data/a11134/a.txt
          3232b.ddsss.txt,32 /data/d13f11/b.txt
          3452d.dsasa.txt,1234 /data/c13af4/f.txt
          .
          """
          
          search_result = re.search(r"^OK.*\n((.|\s)*).", string)
          
          if search_result:
              print(search_result.group(1))
          

          输出是:

          1233a.fdads.txt,23 /data/a11134/a.txt
          3232b.ddsss.txt,32 /data/d13f11/b.txt
          3452d.dsasa.txt,1234 /data/c13af4/f.txt
          

          ^OK.*\n 将找到带有 OK 语句的第一行,但我们不想提取它,所以不带括号。接下来是我们要捕获的部分:((.|\s)*),所以把它放在括号内。在正则表达式的末尾,我们寻找一个点 .,但我们也不想捕获它。

          P.S:我发现这个答案对于理解群体的力量非常有帮助。 https://stackoverflow.com/a/3513858/4333811

          【讨论】:

            【解决方案8】:

            如果 OK 行是第一行,最后一行是点,您可以考虑像这样将它们切掉:

            TestString = '''OK SYS 10 LEN 20 12 43
            1233a.fdads.txt,23 /data/a11134/a.txt
            3232b.ddsss.txt,32 /data/d13f11/b.txt
            3452d.dsasa.txt,1234 /data/c13af4/f.txt
            .
            '''
            print('\n'.join(TestString.split()[1:-1]))
            

            但是,如果这是一个非常大的字符串,您可能会遇到内存问题。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2022-12-04
              • 1970-01-01
              • 1970-01-01
              • 2022-12-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多