正则表达式允许一个或多个单词允许一个空格并使用两个或更多空格作为列

时间:2017-05-01 20:49:50

标签: php regex parsing

我试图逐行解析一些文件并尝试将其标识为列。连续的两列是单词,但分隔模式不止一个空格。由于列之间可以有空格,我在分离这两个时遇到了一些麻烦。

行的例子:

2236        ARGEMIRO PATROCINIO                                   ARGEMIRO                 I       I          UBC            3,8462

1150721     ZACHARY F CONDON                                      ZACH CONDON               I       I          FINTAGE        8,3333

50300       COMERCIAL FONOGRAFICA RGE LTDA.                                                 PF      LI         ABRAMUS       25,0000`

固定

  

obs:它没有显示'2236','ARGEMIRO之间的所有空格   PATROCINIO','ARGEMIRO','我','我','UBC'和'3,8462'

我正在使用这个正则表达式:

(\d+)\s+([\.a-zA-Z\s,'À-úÀ-ÿ()\?\-\/\d]+)\s{2,}([\.a-zA-Z\s,'À-úÀ-ÿ()\?\-\/\d]+)\s{2,}(I|PF|MA)\s{2,}(I|PF|PL|LI|MA|CV|MJ)\s{2,}(\w+)\s{2,}(\d+,\d{4})

但不幸的是,“ARGEMIRO PATROCINIO”即将推出第二款“ARGEMIRO”; “ZACHARY F CONDON”与第二个“ZACH CONDON”一起开启。

所以,

  1. 如何修复此正则表达式以分隔这两个“列”?
  2. 如何在这7列中的两个或更多空格之间抓取任何东西的另一个正则表达式?
  3. 谢谢!

3 个答案:

答案 0 :(得分:1)

我实际上并没有在您粘贴的数据中看到双重空格,但您是这样描述的。您可以在有2个或更多连续空格的地方拆分:

preg_split("/[\s]{2,}/", $data);

DEMO:http://www.phpliveregex.com/p/jWZ(点击" preg_split"在右侧)

答案 1 :(得分:0)

你应该明白贪婪是如何运作的。一旦您的子模式变得懒惰,它将首先被跳过,然后首先尝试后续模式。只有在找不到匹配项的情况下,引擎才会返回到延迟量化的模式,匹配模式匹配的单个字符,然后再次测试后续的子模式。该机制类似于回溯,但前进。

所以,你可能要做的是确保第二和第三列模式 lazy 。 (注意我猜你使用的是/U贪婪交换修饰符,我的建议是不要用它来使模式尽可能清晰):

(\d+)\s+([-.a-zA-Z\s,'À-úÀ-ÿ()?\/\d]+?)\s{2,}([-.a-zA-Z\s,'À-úÀ-ÿ()?\/\d]+?)\s{2,}(I|PF|MA)\s{2,}(I|PF|PL|LI|MA|CV|MJ)\s{2,}(\w+)\s{2,}(\d+,\d{4})

如果您只需要匹配整行,请添加锚点(开头为^,末尾为$)和/m修饰符。

请参阅regex demo

查看[-.a-zA-Z\s,'À-úÀ-ÿ()?\/\d]+?)模式,+? lazy quantifier匹配1 +字符,尽可能少

注意我也进行了一些外观修改:.不需要在字符类中进行转义,而-放置在字符类的开头时,永远不需要转义表示文字-

答案 2 :(得分:0)

我会说通常需要这个正则表达式

/(\d+)\s{2,}([.a-zA-Z,'À-úÀ-ÿ()?\-\/\d]+(?:\s?[.a-zA-Z,'À-úÀ-ÿ()?\-\/\d])*)\s{2,}([.a-zA-Z,'À-úÀ-ÿ()?\-\/\d]+(?:\s?[.a-zA-Z,'À-úÀ-ÿ()?\-\/\d])*)\s{2,}(I|PF|MA)\s{2,}(I|PF|PL|LI|MA|CV|MJ)\s{2,}(\w+)\s{2,}(\d+,\d{4})/

但由于最后一条记录只有6列,所以它不会与最后一条记录相匹配 https://regex101.com/r/YynbpP/1

我的建议是你重新考虑哪些列可以选择 然后相应地调整正则表达式。

例如,第2组和第3组的结构相同 如果您希望第二个是可选的,那么正确的正则表达式就是:

/(\d+)\s{2,}([.a-zA-Z,'À-úÀ-ÿ()?\-\/\d]+(?:\s?[.a-zA-Z,'À-úÀ-ÿ()?\-\/\d])*)(?|\s{2,}((?:[.a-zA-Z,'À-úÀ-ÿ()?\-\/\d]+(?:\s?[.a-zA-Z,'À-úÀ-ÿ()?\-\/\d])*))|())\s{2,}(I|PF|MA)\s{2,}(I|PF|PL|LI|MA|CV|MJ)\s{2,}(\w+)\s{2,}(\d+,\d{4})/

https://regex101.com/r/ohtTfO/2

维护列结构

请注意,如果缺少第3列条目,则很可能没有 弹出一个额外的\s{2,}所以你不能说整件事只是可选的 因为它会将第3列变为空,而不是空字符串。

要解决这个问题,我只使用了分支重置
始终与第3列匹配的(?|\s{2,}(data)|()) 并且如果它不存在则使其成为空字符串......

Formatted(为了方便使用)

 ( \d+ )                                  # (1)
 \s{2,} 
 (                                        # (2 start)
      [.a-zA-Z,'À-úÀ-ÿ()?\-/\d]+ 
      (?:
           \s? 
           [.a-zA-Z,'À-úÀ-ÿ()?\-/\d] 
      )*
 )                                        # (2 end)
 (?|
      \s{2,} 
      (                                        # (3 start)
           (?:
                [.a-zA-Z,'À-úÀ-ÿ()?\-/\d]+ 
                (?:
                     \s? 
                     [.a-zA-Z,'À-úÀ-ÿ()?\-/\d] 
                )*
           )
      )                                        # (3 end)
   |  ( )                                      # (3)
 )
 \s{2,} 
 ( I | PF | MA )                          # (4)
 \s{2,} 
 ( I | PF | PL | LI | MA | CV | MJ )      # (5)
 \s{2,} 
 ( \w+ )                                  # (6)
 \s{2,} 
 ( \d+ , \d{4} )                          # (7)