2017-06-01 92 views
2

我正在写一个Perl程序,需要解析一个用Wiki标记语言编写的表。表格语法使用管道字符'|'分开列。regexp分裂一个字符串,但忽略引号分隔符

| row 1 cell 1 |row 1 cell 2 | row 1 cell 3| 
| row 2 cell 1 | row 2 cell 2 |row 2 cell 3| 

一个单元可以包含零个或多个超链接中,通过示出其语法:

[[wiki:path:to:page|Page Title]] or 
[[wiki:path:to:page]] 

注意,该超链接可包含管道字符。然而,在这里,它是由[[]]括号引用的。

超链接语法不能嵌套。

为了匹配和捕捉第一个单元格中的每个表中的行,

| Potatoes [[path:to:potatoes]]   | Daisies   | 
| Kiki fruit [[path:to:kiwi|Kiwi Fruit]] |    Lemons| 

我想:

qr{\|      # match literal pipe 
    (.*?     # non-greedy zero or more chars 
     (?:\[\[.*?\]\]) # a hyperlink 
    .*?)     # non-greedy zero or more chars 
    \|}x     # match terminating pipe 

它的工作和$ 1含有单元格的内容。

然后,匹配

| Potatoes   | Daisies   | 

我试图使的超级链接可选:

qr{\|      # match literal pipe 
    (.*?     # non-greedy zero or more chars 
     (?:\[\[.*?\]\])? # <-- OPTIONAL hyperlink 
    .*?)     # non-greedy zero or more chars 
    \|}x     # match terminating pipe 

这个工作,但解析

| Kiki fruit [[path:to:kiwi|Kiwi Fruit]] |    Lemons| 

时,我只得到了

Kiki fruit [[path:to:kiwi 

显然,给定选项后,它决定忽略超链接模式并将嵌入管道视为列分隔符。

这里我卡住了。而且我还没有处理超链接在单元格中出现超过一次的可能性,或者在下一次迭代时回退尾部管道成为主管道。

在Perl的split函数中使用正则表达式不是必须的 - 如果它更简单,我可以自己编写分割循环。我看到很多类似的问题被提出,但似乎没有一个能够解决这个问题。

+0

所以你的问题是,一旦你分割管道字符的文本,你不能解析的内容,如果他们可能包含重命名的链接,链接,或没有链接。是对的吗? – Borodin

+0

不,我不能将文本(表格整行的标记)拆分为列,如果它们包含重命名的链接。 – Chap

回答

1
$ perl -MRegexp::Common -E '$_=shift; while (
    /\| # beginning pipe, and consume it 
    ( # capture 1 
    (?: # inside the pipe we will do one of these: 
     $RE{balanced}{-begin=>"[["}{-end=>"]]"} # something with balanced [[..]] 
     |[^|] # or a character that is not a pipe 
    )* # as many of those as necessary 
) # end capture one 
    (?=\|) # needs to go to the next pipe, but do not consume it so g works 
    /xg 
) { say $1 }' '| Kiki fruit [[path:to:kiwi|Kiwi Fruit]] |    Lemons|' 
Kiki fruit [[path:to:kiwi|Kiwi Fruit]] 
      Lemons 

这似乎提取你正在寻找的。不过,我怀疑你最好用适合这种语言的解析器。如果cpan上没有任何东西,我会感到惊讶,但即使不是这样,为此编写解析器仍然可能会更好,尤其是当您开始在需要处理的表中获得更奇怪的东西时。

+0

如下所述,我无法在CPAN或更高版本中找到Perl解决方案。 – Chap

+0

这个答案也处理没有链接的单元格以及具有多个链接的单元格。对我来说,关键的要点是(1)使用Regexp :: Common,并且(2)将单个非管道字符和平衡表达式视为零次或多次出现的“原子”替代方案。简单。 – Chap

相关问题