我能使用Perl中的unpack函数将字符串拆分为字符吗?

8

一种常见的 'Perlism' 是以这种形式生成一个要循环的列表:

for($str=~/./g) { print "the next character from \"$str\"=$_\n"; }

在这种情况下,全局匹配正则表达式返回一个列表,该列表依次从字符串 $str 中获得一个字符,并将该值赋给 $_

除了正则表达式,可以使用 split 以相同的方式或 'a'..'z'map 等。

我正在研究 unpack 以生成对字符串进行逐个解释的字段。我发现 unpack 总是比我的大脑工作方式不太直观,我从未真正深入研究过它。

作为一个简单的例子,我想使用 unpack 生成一个列表,每个元素中都有一个来自字符串的字符(是的 - 我知道我可以使用 split(//,$str)/./g 来实现,但我真的想看看是否可以以这种方式使用 unpack...)

显然,我可以使用一个字段列表来解包,即 unpack("A1" x length($str), $str),但是否有其他类似于 globbing 的方式?即,我是否可以调用 unpack(some_format,$str),无论是在列表上下文中还是在循环中,以便 unpack 将返回格式组中的下一组字符,直到 $str 被耗尽?

我已经阅读了 Perl 5.12 Pack pod Perl 5.12 pack 教程 Perkmonks 教程

这是示例代码:

#!/usr/bin/perl
use warnings;
use strict;

my $str=join('',('a'..'z', 'A'..'Z')); #the alphabet...  

$str=~s/(.{1,3})/$1 /g;                #...in groups of three
print "str=$str\n\n";

for ($str=~/./g) { 
 print "regex: = $_\n";
}

for(split(//,$str)) {
 print "split: \$_=$_\n";
}

for(unpack("A1" x length($str), $str)) {
 print "unpack: \$_=$_\n";
}
1个回答

10

packunpack 模板可以使用括号来分组,就像正则表达式一样。这个组可以在后面添加一个重复计数器。当重复计数器为*时,意味着“重复打包/解包直到没有任何内容可用”。

for(unpack("(A1)*", $str)) {
    print "unpack: \$_=$_\n";
}

你需要运行一个基准测试来找出哪个是最快的。


我知道它一定很简单!现在我试着用它,"(A1)*"将会匹配(我的问题),而"(A1)$i"将会生成$i个字段。太好了!你知道有没有一个好的文档记录这个吗?网络上的大部分资料都不是很好... - dawg
@drewk:在 perldoc -f pack(http://perldoc.perl.org/functions/pack.html)中,“在重复计数的位置提供 * 而不是数字意味着使用剩余的所有项...”,“() 组是用括号括起来的子模板...” - Ether
@Ether:在这种情况下,perldoc中的示例对我来说并没有很好地解释清楚。大多数使用*的情况是以“吞噬剩余部分”的形式出现,比如 unpack 'a3/A A*', '007 Bond J '; gives (' Bond', 'J'),我认为pack/unpack的perldoc可能需要更加清晰明了一些... - dawg
@Ether: pack("@1A((@2A)@3A)", qw[X Y Z])() 组模板下的示例产生了 "\0X\0\0YZ",这只是作者喜欢的一个示例 :-}} - dawg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接