Perl多行递归匹配带嵌套大括号的\rem结构失败求助
问题修正方案
问题背景
需要匹配形如\rem{lp}{含嵌套大括号的文本}的结构,在regex101上测试正则表达式([^\s]*\s*)\\rem\{(?:lp|db)\}(\{((?>[^\{\}]|\n|(?2))*)\})(\s?[^\s]*)可正常工作,但在Perl命令行执行以下命令时,无法匹配test.txt中含换行的目标结构,添加m修饰符也无效:
perl -ne 'while(/([^\s]*\s*)\\rem\{(?:lp|db)\}(\{((?>[^\{\}]|\n|(?2))*)\})(\s?[^\s]*)/g){print ++$a."$&\n";}' test.txt
test.txt内容:
Some text etc word\rem{lp}{ more text {\ce{O2}} further text {\ce{H2O}} . some other text the $m = 48$ ({\ce{O2}}) ps}. \rem{lp}{ more text {\ce{O2}} further text {\ce{H2O}} . some other text the $m = 48$ ({\ce{O2}}) ps where more text {\ce{O2}} further text {\ce{H2O}} . some other text the $m = 48$ ({\ce{O2}}) ps from who more text {\ce{O2}} further text {\ce{H2O}} . some other text the $m = 48$ ({\ce{O2}}) ps.} \rem{lp}{ more text {\ce{O2}} further text {\ce{H2O}} . some other text the $m = 48$ ({\ce{O2}}) ps. more text {\ce{O2}} further text {\ce{H2O}} . some other text the $m = 48$ ({\ce{O2}}) ps.} \subsection{other} Our bla bla bla
问题原因
Perl的-n选项会逐行读取输入文件,每次只处理一行内容。而目标匹配结构存在跨多行的情况,单行内无法包含完整的\rem块,因此正则无法匹配到结果。m修饰符仅改变^和$的匹配范围(从行首/行尾变为字符串首/尾),无法解决逐行处理导致的跨行内容拆分问题。
修正后的命令
使用-0777选项(等价于-slurp)将整个文件一次性读入为单个字符串,让正则可以匹配跨多行的完整结构,同时添加/s修饰符(可选,但能让.匹配换行符,增强正则兼容性):
perl -0777 -ne 'while(/([^\s]*\s*)\\rem\{(?:lp|db)\}(\{((?>[^\{\}]|\n|(?2))*)\})(\s?[^\s]*)/gs){print ++$a."$&\n";}' test.txt
说明
-0777:告诉Perl读取整个文件作为单个字符串,而非逐行处理。/gs:g表示全局匹配所有符合条件的结构;s表示让.匹配任意字符(包括换行符),虽当前正则已用\n显式匹配换行,但添加s不影响现有逻辑,还能提升正则通用性。
内容的提问来源于stack exchange,提问作者atapaka
相关产品推荐
相关产品推荐

