将包转换为 perl6
Posted
技术标签:
【中文标题】将包转换为 perl6【英文标题】:Converting pack to perl6 【发布时间】:2018-11-18 20:26:20 【问题描述】:我想将以下内容从 perl5 转换为 perl6,
$salt = pack "C*", map int rand 256 1..16;
它创建一个由 16 个字符组成的字符串,其中每个字符都有一个从 0 到 255 的随机值。Perl5 不会为这些字符分配任何语义,因此它们可以是字节、Unicode 代码点或其他东西。
我觉得我能过得去
$salt = (map (^256).pick.chr,^16).join;
但我一直坚持使用 pack,这是我的尝试,
use experimental :pack;
my $salt = pack("C*",(map (^256).pick , ^16)).decode('utf-8');
say $salt;
say $salt.WHAT;
结果可能是错误,
Malformed termination of UTF-8 string
in block <unit> at test.p6 line 3
或者类似的,
j
(Str)
我的想法是打包整数 List 将返回一个 Buf 然后解码应该产生所需的 Str。
更新:
正如评论和回答中所建议的那样,Buf
是要使用的正确对象。现在跟进pack
部分,
perl6 -e 'use experimental :pack; my $salt = pack("C*",(map (^256).pick , ^16));say $salt;say $salt.WHAT;'
缓冲区:0x (BUF)
只包装一个单位
另一方面,使用 P5pack(由 Scimon 建议)返回错误
perl6 -e 'use P5pack; my $salt = pack("C*",(map (^256).pick , ^16));say $salt;say $salt.WHAT;'
Cannot convert string to number: base-10 number must begin with valid digits or '.' in '⏏*' (indicated by ⏏)
in sub one at /home/david/.rakudobrew/moar-master/install/share/perl6/site/sources/D326BD5B05A67DBE51C279B9B9D9B448C6CDC401 (P5pack) line 166
in sub pack at /home/david/.rakudobrew/moar-master/install/share/perl6/site/sources/D326BD5B05A67DBE51C279B9B9D9B448C6CDC401 (P5pack) line 210
in block <unit> at -e line 1
更新 2:
我没有发现差异。
perl6 -e 'say (map (^256).pick, ^16).WHAT;'
(Seq)
perl6 -e 'say Buf.new((^256).roll(16)).WHAT;'
(Buf)
现在列出它们,
perl6 -e 'use experimental :pack; my $salt = pack("C*",(Buf.new((^256).roll(16)).list));say $salt;say $salt.WHAT;'
Buf:0x<39>
(Buf)
和
perl6 -e 'use P5pack; my $salt = pack("C*",Buf.new((^256).roll(16)).list);say $salt;say $salt.WHAT;'
Cannot convert string to number: base-10 number must begin with valid digits or '.' in '⏏*' (indicated by ⏏)
in sub one at /home/david/.rakudobrew/moar-master/install/share/perl6/site/sources/D326BD5B05A67DBE51C279B9B9D9B448C6CDC401 (P5pack) line 166
in sub pack at /home/david/.rakudobrew/moar-master/install/share/perl6/site/sources/D326BD5B05A67DBE51C279B9B9D9B448C6CDC401 (P5pack) line 210
in block <unit> at -e line 1
参考:
Buffers and Binary IO
A first approach to pack/unpack in Perl 6
提前感谢您的帮助。
【问题讨论】:
你到底想做什么?如果您想从前 256 个 Unicode 代码点中随机选择,请使用decode('iso-8859-1')
。不过,这是一件奇怪的事情。是什么让您认为它不应该是 Buf
?如果您尝试生成(不安全的)加密密钥,那么您正在生成任意字节,Buf
将是合适的类型。
@ikegami,感谢您的评论。 >> 你到底想做什么? - 我在 Rosetta Code 的一项任务中看到 P5 行,并想将其翻译为 P6 作为学习过程。
一个注释 ^256.roll(16)
应该给你 16 个随机数而不需要地图。等我起来了,我再看看。
@Scimon 谢谢,你说得对,请看我的更新2。
【参考方案1】:
正如 ikegami 在对您的问题的评论中所说,您确实应该使用 Buf
,它基本上是一个字节“字符串”。
my $salt = Buf.new((^256).roll(16));
您可以将其写入文件,例如:
spurt 'foo', $salt, :bin;
或使用 base-64 编码:
use MIME::Base64;
my $encoded = MIME::Base64.encode($salt);
但是,如果您需要这个相当安全,请查看Crypt::Random
use Crypt::Random;
my $salt = crypt_random_buf(16);
【讨论】:
【参考方案2】:最简单的方法可能是使用https://modules.perl6.org/dist/P5pack:cpan:ELIZABETH,它允许您使用 Perl5 包语法。
【讨论】:
感谢您的建议,请参阅我的更新。也许我用错了?【参考方案3】:显然"C" x 16
有效,但"C*"
无效。别问,我也不知道为什么。 :-D
perl6 -e 'use experimental :pack; my $salt = pack("C" x 16,(Buf.new((^256).roll(16)).list));say $salt;say $salt.WHAT;'
Buf:0x<64 71 D4 E6 E6 AD 7B 1C DD A2 62 CC DD DA F3 08>
(Buf)
另一方面,解包确实有效。
perl6 -e 'use experimental :pack; my $salt = pack("C" x 16,(Buf.new((^256).roll(16)).list)).unpack("C*");say $salt;say $salt.WHAT;'
(35 101 155 237 153 126 109 193 94 105 70 111 59 51 131 233)
(List)
总而言之,mscha 的答案是 P6'ish 和整洁。这是一次愚蠢的往返pack
Buf
列表以获得Buf
。
至于其他包转换,注意here中的两个关键点,
Here is the difference between Perl 5 and Perl 6 pack/unpack:
Perl 5 Perl 6
pack(List) --> Str pack(List) --> Buf
unpack(Str) --> List unpack(Buf) --> List
和
一些 Perl 5 模板规则假定 Buf 和 Str 之间有一条简单的双向街道。在 Perl 5 中,Buf 和 Str 之间根本没有真正的区别,而 Perl 5 相当多地使用了这一点。
编辑:修正错字,s/masha/mscha/;
【讨论】:
s/mascha/mscha/ 抱歉,错字已修正。以上是关于将包转换为 perl6的主要内容,如果未能解决你的问题,请参考以下文章