我正在尝试打印与"备忘单"匹配的org mode节点
节点以""(星号)序列开始,并在比第一个""(星号)序列短或相等的下一个"*"(星号)序列结束。节点仅从行首开始。
以下是我目前掌握的情况:
#! /usr/bin/perl
$data= <<EOF;
not printed
* not printed
** cheatsheet printed
printed
* not printed
no printed
EOF
$\="\n";
my @data = split /\n/, $data;
foreach $_( @data ) {
/^((\*)+) cheatsheet/ ... /^((\*)){1,length("$1")}/ and print ;
}
程序应打印
** cheatsheet printed
printed
我的意图是让perl用length("$1")
代替2,这样第二个匹配操作就被动态转换为:
/^((\*)){1..2}/
因此在"* 未打印"行停止
错误消息:
Nested quantifiers in regex; marked by <-- HERE in m/^((\*)){1,length("** <-- HERE ")}/ at ./tst.pl line 14.
即使perl的行为符合我的预期,它仍然会打印行"* not printed"。任何关于如何解决这个问题的想法都是受欢迎的。
我知道org模式的解析器模块,我想用regex来练习。
3条答案
按热度按时间uxhixvfz1#
基本上就是
在我们的情况下,这意味着
您希望在第二个匹配项中使用第一个匹配项所匹配的星数。
除了跟踪星星的数量,我还删除了一些不必要的括号,并在第二个正则表达式中添加了一个空格,类似
(?!\*)
的内容非常重要,因为/^\*{1,2}/
与*****
匹配。顺便说一下,我们可以避免动态地构建模式。
使用
...
:cl25kdpy2#
匹配整个文本,而不是逐行匹配,并使用负前瞻。下面的摘录稍微扩展了您的测试数据,只是为了确保**cheatsheet下的子节点会得到正确处理
下面是另一个版本,遵循池上的建议,添加了一些注解。由于/s标志被删除,'.'的含义发生了变化,所以我们也必须在“cheatsheet”行的末尾显式地包含\n。
sdnqo3pr3#
可以使用Perl * Code Construct *
(??{ code })
之一来构造正则表达式段它是内联的,实时执行的。返回值是一个模式。
这将使用regex系统变量
$^N
来获取上次获取的捕获值在使用它之前。
通过取长度,范围量词可以被构造为代码段的一部分。
注意,量词不能跟在空的后面,所以星号必须包含在结构中。
使用预视,匹配会继续进行,直到找到下一个落在该范围内的星号行。
注意,我是按照规范来做的,所以一行的开头比所需的星号范围多 * 个星号就可以匹配,这很容易克服。