作为实践,我正在尝试解析一些作为shell命令输出的标准文本。
pool: thisPool
state: ONLINE
status: Some supported features are not enabled on the pool. The pool can
still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
the pool may no longer be accessible by software that does not support
the features. See zpool-features(5) for details.
scan: none requested
config:
NAME STATE READ WRITE CKSUM
homePool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-WDC_WD5000AZLX-00CL5A0_WD-WCC3F7NUE93C ONLINE 0 0 0
ata-WDC_WD5000AZLX-00CL5A0_WD-WCC3F7RE2A4F ONLINE 0 0 0
cache
ata-KINGSTON_SV300S37A60G_50026B7261025D7E-part3 ONLINE 0 0 0
errors: No known data errors
我想使用Perl6语法,我想在单独的令牌或正则表达式中捕获每个字段。因此,我做了以下语法:
grammar zpool {
regex TOP { \s+ [ <keyword> <collection> ]+ }
token keyword { "pool: " | "state: " | "status: " | "action: " | "scan: " | "config: " | "errors: " }
regex collection { [<:!keyword>]* }
}
我的想法是,正则表达式找到一个关键字,然后开始收集所有数据,直到下一个关键字。然而,每次我都会得到“池”:-
keyword => 「pool: 」
collection => 「homePool
state: ONLINE
status: Some supported features are not enabled on the pool. The pool can
still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
the pool may no longer be accessible by software that does not support
the features. See zpool-features(5) for details.
scan: none requested
config:
NAME STATE READ WRITE CKSUM
homePool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-WDC_WD5000AZLX-00CL5A0_WD-WCC3F7NUE93C ONLINE 0 0 0
ata-WDC_WD5000AZLX-00CL5A0_WD-WCC3F7RE2A4F ONLINE 0 0 0
cache
ata-KINGSTON_SV300S37A60G_50026B7261025D7E-part3 ONLINE 0 0 0
errors: No known data errors
」
我不知道当它找到一个关键字时,如何让它停止吃掉字符,然后将其视为另一个关键字。
匿名用户
尽管我不时地喜欢好的语法,但通过调用split可以更容易地解决这个问题:
my $input = q:to/EOF/;
pool: thisPool
state: ONLINE
status: Some supported features are not enabled on the pool. The pool can
still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
the pool may no longer be accessible by software that does not support
the features. See zpool-features(5) for details.
scan: none requested
config:
NAME STATE READ WRITE CKSUM
homePool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-WDC_WD5000AZLX-00CL5A0_WD-WCC3F7NUE93C ONLINE 0 0 0
ata-WDC_WD5000AZLX-00CL5A0_WD-WCC3F7RE2A4F ONLINE 0 0 0
cache
ata-KINGSTON_SV300S37A60G_50026B7261025D7E-part3 ONLINE 0 0 0
errors: No known data errors
EOF
my @delimiter = <pool state status action scan config errors>;
my %fields;
for $input.split( / ^^ \h* (@delimiter) ':' \h*/, :v)[1..*] -> $key, $value {
%fields{ $key[0] } = $value.trim;
}
say %fields.perl;
这是通过对已知键进行拆分,丢弃第一个元素(因为我们知道输入以键而不是值开头),然后同步迭代键和值来工作的。
现在,由于您要求语法,我们可以通过将每个值替换为.?
(任何字符串,但尽可能短)来轻松地将拆分
调用转换为纯正则表达式。
现在让我们给它一些更多的结构:
my @delimiter = <pool state status action scan config errors>;
grammar ZPool {
regex key { @delimiter }
regex keychunk { ^^ \h* <key> ':' }
regex value { .*? }
regex chunks { <keychunk> \h* <value> }
regex TOP { <chunks>+ }
}
我们可以从嵌套的匹配树中提取结果,或者使用有状态的操作对象进行欺骗:
class ZPool::Actions {
has $!last-key;
has %.contents;
method key($m) { $!last-key = $m.Str }
method value($m) { %!contents{ $!last-key } = $m.trim }
}
然后使用它:
my $actions = ZPool::Actions.new;
ZPool.parse($input, :$actions);
say $actions.contents.perl;
< code>key和< code>keychunk不需要回溯,所以可以将它们从< code>regex改为< code>token。
当然,使用. ?
和回溯可能被认为是作弊,因此您可以使用raiph提到的技巧,在value
正则表达式中带有负面展望。
问题1
您已经编写了<代码>
和<code>
但是没有Unicode属性
:关键字
。
因此,否定断言将始终为真,并且每次都将匹配输入的单个字符。
所以,正如你所知道的,这个模式只是通过文本的其余部分来咀嚼。
问题2
修复问题 1 后,会出现第二个问题。
<代码>
相比之下,< code >
解决这两个问题后,您将获得预期的输出。(您将看到的下一个问题是
config
关键字不起作用,因为输入文件示例中的 :
in config:
后跟空格。
所以,通过一些清理:
my @keywords = <pool state status action scan config errors> ;
say grammar zpool {
token TOP { \s+ [ <keyword> <collection> ]* }
token keyword { @keywords ': ' }
token collection { [ <!keyword> . ]* }
}
我已将所有模式转换为
令牌
声明。通常,除非您知道自己需要其他东西,否则请始终使用令牌
。(正则表达式
支持回溯。如果你不小心,这可能会大大减慢速度。规则
使规则中的空格变得重要。
我已经将关键字提取到一个数组中。
@关键字
表示@关键字[0]|@关键字[1]|…
。
我添加了一个<code>
在
之后
如果您没有看到它们,请注意可用的语法调试选项是您的朋友。
呵呵
在Perl 5中,我能够多次设置一个选项,就像在这个问题中一样: 多次使用相同选项的Perl Getopt 我想知道是否有可能对Perl 6和MAIN子级做同样的事情?
我正在尝试创建一个语法。到目前为止,这是我的代码: 我真的只是希望语法从输入中创建一个列表/哈希表树。代码的输出是: 看起来还不错。perl6似乎在解码这样一个事实,即字段描述符由多个字段描述符组成,但实际上似乎并没有将它们放入列表中。我可以说$fds ,但我不能说$fds[0] 。为什么前者“起作用”,而后者不起作用? 我必须承认,我对正在发生的事情掌握得相当薄弱。使用规则而不是令牌会更好吗?我
译注: 在原文标题后加上小括号以表示其为方法名,以与一般标题加以区别。 exit() 在学习怎么处理文件之前,我们先来了解一些实用的函数。 exit()能够使程序在任何调用它的地方退出,即无需运行到最后一行就结束。 tutorial/files/exit.p6 #!/usr/bin/env perl6 use v6; say "hello"; exit; say "world"; warn
这是我第一次使用YAML文件,所以我首先想到的是找到任何可以帮助我解析文件的库。 我找到了两个库,YamlBean和snakeyaml。我不确定我要用哪一个。 下面是我试图解析的文件的一个示例: 该文件将动态更改,所以我不知道该文件将包含多少用户或组。 有人能帮我开始吗?最好的图书馆是什么?YamlBean还是Snakeyaml? 我想,我需要将这些信息保存在一个可以轻松重复的东西中。
详细内容请看这里
我正在玩基于Windows上的MoarVM构建的perl6版本。我创建了一些perl6文件并想将其编译为exe。我尝试了以下操作: 现在我想把r编译成可执行文件 我发现这个链接谈论如何使用鹦鹉,但我正在使用MoarVM目标:http://perlgeek.de/blog-en/perl-6/my-first-executable.writeback 我的问题如何将MoarvVM目标文件编译为Win