既然木有 Star 包,那么安装好 MoarVM 上的 Rakudo 后我们就有必要先自己把 panda 之类的工具编译出来。这一步需要注意一下你的 @*INC 路径和实际的 $PERL6LIB 路径,已经编译之后的 panda 存在的 $PATH 是不是都正确,如果不对的修改一下 ~/.bashrc 就好了。
类:
我的尝试迁移对象是一个很简单的 Puppet 的 ENC 脚本,只涉及 SQLite 的读取,以及 YAML 格式的输出。通过 panda install DBIish 命令即可安装好 DBIish 模块。
脚本本身修改起来难度不大,结果如下:
functionreg_escape($str)
代码如下
{
#!/usr/bin/env perl6
use v6;
use DBIish;
use YAML;
my $base_dir = "/etc/puppet/webui";
# 函数在 Perl6 中依然使用 sub 关键字定义,不过有个超酷的特性是 multi
sub
# 脚本中没有用到,但是在 YAML::Dumper 中遍地都是,这里也提一句。
# MAIN 函数在 Perl6 里可以直接用 :$opt 命令参数起 getopt 的作用
# 不过 ENC 脚本就是直接传一个主机名,用不上这个超酷的特性
sub MAIN($node) {
# connect 方法接收参数选项是 |%opts,所以可以把哈希直接平铺写
# 这个 | 的用法一个月前在《Using Perl6》里看到过
my $dbh = DBIish.connect( 'SQLite', database =>
"{$base_dir}/node_info.db" );
my $sth =
$dbh.prepare("select * from
node_info where node_fqdn = ?");
$sth.execute("$node");
my $ret = $sth.fetchrow_hashref;
my $res;
if ( !$ret ) {
$res = {
# Perl5 的 qw() 在 Perl6 里直接写成 <> 。也不用再通过 []
来指明是引用
classes => <puppetd repos>,
environment => 'testing',
};
}
else {
$res = {
environment => $ret{'environment'},
parameters => { role => $ret{'role'} },
classes => {},
};
# 这个 for 的用法,在 Perl5 的 Text::Xslate 模板里就用过
for split(',', $ret{'classes'}) -> $class {
if ( $class eq 'nginx' )
{
# 这个 <== 符号指明数据流方向,完全可以把数组倒过来,然后用 ==>
写这行
# 如果不习惯这种流向操作符的,可以用,号,反正不能跟 Perl5
那样啥都不写
#
这里比较怪的一点是我试图把这么长的一句分成多行写,包括每行后面加,我看到
YAML 代码里就用分行了,但是我这就会报错
# Perl6 的正则变化较大,这里 /^#/ 要写成 /^'#'/ 或者 /^x23/
# 正则 // 前面不加 m// 不会立刻开始匹配
# 原先的 s///g 可以写作 s:g///,也可以写作对象式的 .subst(m//, '',
:g),. 前面为空就是默认的 $_
# 捕获的数据存在 @() 数组里,也可以用 $/[i] 的形式获取
# 字符串内插时,不再写作 ${*},而是 {$*} 的形式
# 命名捕获这里没用上,写个示例:
# $str ~~ /^(w+?)$<laststr>=(w ** 4)w$/;
# $/<laststr>.chomp.say;
# 注意里面的 w{4} 变成了 w ** 4
my @needs <== map { .subst(m/^(.+):(d+)$/, "{$/[0]}
max_fails=30 weight={$/[1]}", :g) } <== grep { !m/^x23/ } <==
split(',', $ret{'extstr'});
$res{'classes'}{'nginx'}{'iplist'} = @needs;
}
else {
# Perl5 的 undef 不再使用,可以使用 Nil 或者 Any 对象
$res{'classes'}{$class} = Nil;
}
}
};
$dbh.disconnect();
# 这个 dump 就是 YAML 模块导出的函数
# Perl6 的模块要导出函数不再需要 Exporter 那样,直接用 our sub
dump($obj) {} 就可以了
say dump($res);
};
$conversions=array("^"=>"^","["=>"[","."=>".","$"=>"$","{"=>"{","*"=>"*","("=>"(","\" => "\\", "/" => "/", "+" => "+", ")" => ")", "|" => "|", "?" => "?", "<" => "<", ">" => ">" );
但是麻烦的是 YAML 模块本身,这个模块是 ingydotnet 在好几年前草就,后来就没管了,实际现在压根跑不起来。花了半天时间,一边学习一边修改,总算修改正常了。主要涉及了 Attribute 对象,Nil 对象,twigls 前缀符,:exists 定义几个概念,以及 YAML 格式本身的处理逻辑。
returnstrtr($str,$conversions);
YAML 模块修改对比如下:
}
代码如下
/**
diff --git a/lib/YAML/Dumper.pm b/lib/YAML/Dumper.pm
index d7a7981..ec47341 100644
--- a/lib/YAML/Dumper.pm
+++ b/lib/YAML/Dumper.pm
@@ -2,16 +2,16 @@ use v6;
class YAML::Dumper;
has $.out = [];
-has $.seen is rw = {};
+has $.seen = {};
has $.tags = {};
has $.anchors = {};
has $.level is rw = 0;
-has $.id is rw = 1;
+has $.id = 1;
has $.info = [];
method dump($object) {
$.prewalk($object);
- $.seen = {};
+ $!seen = {};
$.dump_document($object);
return $.out.join('');
}
@@ -45,11 +45,11 @@ method dump_collection($node, $kind, $function) {
method check_special($node) {
my $first = 1;
- if $.anchors.exists($node.WHICH) {
- if $.anchors.exists($node.WHICH) {
+ if $.anchors{$node.WHICH}:exists {
push $.out, ' ', '&' ~ $.anchors{$node.WHICH};
$first = 0;
}
- if $.tags.exists($node.WHICH) {
+ if $.tags{$node.WHICH}:exists {
push $.out, ' ', '!' ~ $.tags{$node.WHICH};
$first = 0;
}
@@ -64,7 +64,7 @@ method indent($first) {
return;
}
if $.info[*-1]<kind> eq 'seq' &&
$.info[*-2]<kind> eq 'map' {
- $seq_in_map = 1;
+ $seq_in_map = 0;
}
}
push $.out, "n";
@@ -155,7 +155,8 @@ method dump_object($node, $type) {
$.tags{$repr.WHICH} = $type;
for $node.^attributes -> $a {
my $name =
$a.name.substr(2);
- my $value = pir::getattribute__PPs($node, $a.name);
#RAKUDO
+ #my $value = pir::getattribute__PPs($node, $a.name);
#RAKUDO
+ my $value = $a.get_value($node); #for
non-parrot
$repr{$name} = $value;
}
$.dump_node($repr);
这里的 $.seen 和 $!seen 是不是晕掉了?其实 $.seen 就相当于先声明了
$!seen 后再自动创建一个 method seen() { return $!seen }。
* Strip attribute Class
另一处是 pir::getattribute__PPs() 函数,pir 是 parrot 上的语言,而 MoarVM 和 JVM 上都是先实现了一个 nqp 再用 nqp 写 Perl6,不巧的是这个 pir 里的 getattribute__PPs() 刚好至今还没有对应的 nqp 方法。(在 pir2nqp.todo 文件里可见)
* Remove attributes from XML elements
所以只能用高级的 Perl6 语言来做了。
* @author David (semlabs.co.uk)
总的来说,这个 yaml-pm6 代码里很多地方都是试来试去,同样的效果不同的写法,又比如 .WHICH 和 .WHAT.perl 也是混用。 而且我随手测试了一下,即使在 parrot 上,用 pir::getattribute__PPs 的速度也比 Attribute.get_value 还差点点。
* @version 0.2.1
最后提一句,目前 ENC 脚本在 perl5、perl6-m、perl6-p、perl6-j 上的运行时间大概分别是 0.13、1.5、2.8、12s。MoarVM 还差 Perl5 十倍,领先 parrot 一倍。不过 JVM 本身启动时间很长,这里不好因为一个短时间脚本说它太慢。
*/
另外还试了一下如果把我修改过的 YAML::Dumper 类直接写在脚本里运行,也就是不编译成 moarvm 模块,时间大概是 2.5s,比 parrot 模块还快点点。
classcleanHtml{
不过如何把 perl6 脚本本身编译成 moarvm 的 bytecode 格式运行还没有研究出来,直接 perl6-m --target=mbc --output=name.moarvm name.pl6 得到的文件运行 moar name.moarvm 的结果运行会内存报错。
public$str='';
原文来自:tiejiang.org
public$allow=array();
public$exceptions=array();
public$ignore=array();
publicfunctionstrip($str)
{
$this->str =$str;
if(is_string($str) &&strlen($str) > 0 )
{
$res=$this->findElements();
if(is_string($res) )
return$res;
$nodes=$this->findAttributes($res);
$this->removeAttributes($nodes);
}
return$this->str;
}
privatefunctionfindElements()
{
# Create anarrayof elements with attributes
$nodes=array();
preg_match_all("/<([^ !/>n]+)([^>]*)>/i",$this->str,$elements);
foreach($elements[1]as$el_key=>$element)
{
if($elements[2][$el_key] )
{
$literal=$elements[0][$el_key];
$element_name=$elements[1][$el_key];
$attributes=$elements[2][$el_key];
if(is_array($this->ignore ) && !in_array($element_name,$this->ignore ) )
$nodes[] =array('literal'=>$literal,'name'=>$element_name,'attributes'=>$attributes);
}
}
# Return the XMLifthere were no attributes to remove
if( !$nodes[0] )
return$this->str;
else
return$nodes;
}
privatefunctionfindAttributes($nodes)
{
# Extract attributes
foreach($nodesas&$node)
{
preg_match_all("/([^ =]+)s*=s*["|']{0,1}([^"']*)["|']{0,1}/i",$node['attributes'],$attributes);
if($attributes[1] )
{
foreach($attributes[1]as$att_key=>$att)
{
$literal=$attributes[0][$att_key];
本文由澳门新葡亰网址大全发布于网络时代,转载请注明出处:Perl6 的 YAML::Dumper 模块使用详解
关键词: