3

我有一个由四部分组成的图像文件名:

  1. $Directory(图片所在的目录)
  2. $Name(对于一个艺术网站,这是画名参考#)
  3. $File(图像文件名减去扩展名)
  4. $Extension(图片扩展名)
$example 100020003000.png

我希望相应地分解:

$dir=1000 $name=2000 $file=3000 $ext=.png

我想知道 substr 是否是分解传入的最佳选择,$example这样我就可以使用 4 个变量来做一些事情,比如验证/错误检查,从它的$Name赋值中获取详细的名称等等。我找到了这篇文章:

解压速度比 substr 快吗? 所以,在我的初学者“石头工具”方法中:

my $example = "100020003000.png";
my $dir = substr($example, 0,4);
my $name = substr($example, 5,4);
my $file = substr($example, 9,4);
my $ext = substr($example, 14,3); # will add the the  "." later #

那么,我可以使用解包,或者甚至是另一种更有效的方法吗?

我也想避免加载任何模块,除非这样做会因为某种原因使用更少的资源。模组是我喜欢的很棒的工具,但我认为这里没有必要。

我意识到我可能应该将变量推入数组/散列但是,我真的是这里的初学者,我需要进一步说明如何做到这一点以及如何将它们拉回来。

感谢 stackoverflow.com 上的每一个人!

4

5 回答 5

12

绝对地:

my $example = "100020003000.png";
my ($dir, $name, $file, $ext) = unpack 'A4' x 4, $example;

print "$dir\t$name\t$file\t$ext\n";

输出:

1000 2000 3000 .png
于 2009-10-07T22:00:04.630 回答
5

我只是为此使用正则表达式:

my ($dir, $name, $file, $ext) = $path =~ m:(.*)/(.*)/(.*)\.(.*):;

或者,为了匹配您的具体示例:

my ($dir, $name, $file, $ext) = $example =~ m:^(\d{4})(\d{4})(\d{4})\.(.{3})$:;
于 2009-10-07T21:57:58.160 回答
3

使用unpack很好,但由于元素都是相同的宽度,正则表达式也非常简单:

my $example = "100020003000.png";
my ($dir, $name, $file, $ext) = $example =~ /(.{4})/g;
于 2009-10-07T22:22:29.863 回答
1

它不是解包,但由于您有 4 个字符组,您可以使用有限拆分,并捕获:

my ($dir, $name, file, $ext) = grep length, split /(....)/, $filename, 4;

这是相当模糊的,所以我可能不会使用它,但拆分中的捕获是一个经常被忽视的能力。

所以,这里解释一下这段代码的作用:

步骤 1.split使用捕获括号将模式捕获的值添加到其输出流中。流包含字段和分隔符的混合。

qw( a 1 b 2 c 3 ) == split /(\d)/, 'a1b2c3';

步骤 2.split使用 3 个参数限制字符串被拆分的次数。

qw( a b2c3 ) == split /\d/, 'a1b2c3', 2;

第 3 步。现在,当我们使用几乎匹配任何内容的分隔符模式时/(....)/,我们会得到一堆空(0 长度)字符串。我用字符标记了分隔符D,用F:

 ( '', 'a', '', '1', '', 'b', '', '2' ) == split /(.)/, 'a1b2';
   F    D   F    D   F    D   F    D

第 4 步。因此,如果我们将字段数限制为 3,我们将得到:

 ( '', 'a', '', '1', 'b2' ) == split /(.)/, 'a1b2', 3;
   F    D   F    D   F  

第 5 步。把它们放在一起,我们可以做到这一点(我使用了.jpeg扩展名,以便扩展名超过 4 个字符):

 ( '', 1000, '', 2000, '', 3000, '.jpeg' ) = split /(....)/, '100020003000.jpeg',4;
   F   D     F   D     F   D     F       

第 6 步。第 5 步几乎是完美的,我们需要做的就是去掉空字符串,我们就很好了:

( 1000, 2000, 3000, '.jpeg' ) = grep 长度,拆分 /(....)/, '100020003000.jpeg',4;

这段代码有效,而且很有趣。但它并不比任何其他解决方案更紧凑。我没有进行基准测试,但如果它赢得任何速度或内存效率奖,我会感到非常惊讶。

但真正的问题是,它对于真正的代码来说太棘手了。用于split捕获分隔符(可能还有一个最终字段),同时丢弃字段数据太奇怪了。它也很脆弱:如果一个字段改变长度,代码就会被破坏并且必须重写。

所以,实际上不要这样做。

至少它提供了一个机会来探索一些鲜为人知的特性split

于 2009-10-08T18:44:46.753 回答
0

两者都substrunpack您的思维偏向于固定布局,而正则表达式解决方案更倾向于带有分隔符的灵活布局。

您给出的示例似乎是固定布局,但目录通常通过分隔符与文件名分隔(例如,POSIX 样式文件系统的斜杠,MS-DOS 的反斜杠等)所以您实际上可能有两种情况;将目录和文件名分开(甚至目录/名称/扩展名)的正则表达式解决方案,然后是名称部分本身的固定长度方法。

于 2009-10-07T22:10:23.930 回答