拆分字符串但忽略带引号的定界符的正则表达式
regexp that splits a string but ignores a quoted delimiter
我正在编写一个 Perl 程序,需要解析用 Wiki 标记语言编写的 table。 table 语法使用管道符 '|'分隔列。
| 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]]
请注意,超链接可能包含竖线字符。但是,这里是 [[..]] 括号中的 "quoted"。
超链接语法不能嵌套。
为了匹配和捕获每个 table 行中的第一个单元格,
| 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
函数中使用正则表达式 -- 如果更容易的话,我可以自己编写拆分循环。我看到很多类似的问题被问到,但 none 似乎对这个问题的处理足够密切。
$ 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 }' '| Kiki fruit [[path:to:kiwi|Kiwi Fruit]] | Lemons|'
Kiki fruit [[path:to:kiwi|Kiwi Fruit]]
Lemons
这似乎提取了您要查找的内容。但是,我怀疑您最好使用适合这种语言的解析器。如果 cpan 上没有任何东西,我会感到惊讶,但即使没有,为此编写一个解析器可能仍然更好,尤其是当你开始在你的表中得到更多你需要处理的奇怪的东西时。
我正在编写一个 Perl 程序,需要解析用 Wiki 标记语言编写的 table。 table 语法使用管道符 '|'分隔列。
| 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]]
请注意,超链接可能包含竖线字符。但是,这里是 [[..]] 括号中的 "quoted"。
超链接语法不能嵌套。
为了匹配和捕获每个 table 行中的第一个单元格,
| 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
函数中使用正则表达式 -- 如果更容易的话,我可以自己编写拆分循环。我看到很多类似的问题被问到,但 none 似乎对这个问题的处理足够密切。
$ 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 }' '| Kiki fruit [[path:to:kiwi|Kiwi Fruit]] | Lemons|'
Kiki fruit [[path:to:kiwi|Kiwi Fruit]]
Lemons
这似乎提取了您要查找的内容。但是,我怀疑您最好使用适合这种语言的解析器。如果 cpan 上没有任何东西,我会感到惊讶,但即使没有,为此编写一个解析器可能仍然更好,尤其是当你开始在你的表中得到更多你需要处理的奇怪的东西时。