拆分包含Perl中数字的字符串

时间:2012-11-05 01:00:37

标签: perl split

我想拆分一个字符串(有数字)。在下面的示例中,我想将字符串拆分为k和k1。

my @array1=("0","23","1","4","65","7");
$k=1;$k1=0;
my $j=join("",@array1);
my @ar=split(/($k|$k1)/,$j);
print join(";",@ar),"\n\n";

输出为;0;23;1;4657

在上面的输出中,额外的分号“;”正在打印

预期输出为0;23;1;4657

当我为以下示例尝试上面的代码时,输​​出是正确的:(0;5;123;4;6);额外的分号不在这里打印。

my @array1=("0","5","1234","6");
$k=5;$k1=4;

我不确定,出于什么原因,第一个例子是打印额外的分号“;”

有人可以帮助我吗?

5 个答案:

答案 0 :(得分:2)

不同之处在于当你分开第一个字符时,你会在开头得到一个空值。因此额外;在0之前(和“”之后)。你会同样找到;;拆分两个相邻的字符时

所以绝对最简单的修复方法是使用grep删除空字符串:

my @ar=split(/($k|$k1)/,$j);
@ar = grep /./, @ar;

这将删除@ar。

中的空字符串

从更大的角度来看,你可能想看看为什么你要加入字符串只是为了将它们分开。你也在一个地方分裂,可能出现在另一个地方。就像$ k = 1和@ array1 =(11,23,1,4);

答案 1 :(得分:1)

这是一个非常人为的例子,有很多问题(例如$ k和$ k1需要用“my”声明,你应该use strict等)并且它可能会做你不做的事情想。

底线以及您看到前导分号的原因是,如果您使用在字符串开头匹配的分隔符进行拆分,split将返回一个空列表元素。

print join ';', split /0/, '0123';

答案 2 :(得分:1)

在这段代码中有一些有趣的行为我不知道,并且在其他答案中没有提到。正则表达式上split通常会发生的事情是,您要拆分的字符将从结果中省略。但是,似乎如果在正则表达式中捕获括号,则捕获的材料将保留在结果中。

脚本

#!/usr/bin/env perl

use strict;
use warnings;

my @array1 = ("0", "23", "1", "4", "65", "7");
my $j = join("", @array1);
my $k;
my $k1;
my @ar;
print "Join [$j]\n";

$k = 1;
$k1 = 0;
printf "%-25s", "Version 1 /($k|$k1)/:";
@ar = split(/($k|$k1)/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 2 /($k|$k1)/:";
$k = "1";
$k1 = "0";
@ar = split(/($k|$k1)/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 3 /[01]/:";
@ar = split(/[01]/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 4 /(0|1)/:";
@ar = split(/(0|1)/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 5 /0|1/:";
@ar = split(/0|1/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 6 /([46])/:";
@ar = split(/([46])/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 7 /(?:[46])/:";
@ar = split(/(?:[46])/, $j);
print "[", join(";", @ar), "]\n";

输出

Join [02314657]
Version 1 /(1|0)/:       [;0;23;1;4657]
Version 2 /(1|0)/:       [;0;23;1;4657]
Version 3 /[01]/:        [;23;4657]
Version 4 /(0|1)/:       [;0;23;1;4657]
Version 5 /0|1/:         [;23;4657]
Version 6 /([46])/:      [0231;4;;6;57]
Version 7 /(?:[46])/:    [0231;;57]

如您所见,当分割字符串的正则表达式中存在捕获括号时,将保留(捕获的)分割字符。如果括号丢失或明确无法捕获(版本7),则不会保留拆分字符。

而且,如果您仔细阅读本手册,split说明确实包含以下段落:

  

如果PATTERN包含capturing groups,则对于每个分隔符,将为组捕获的每个子字符串生成一个附加字段(按照backreferences的顺序指定组的顺序;如果任何组都不匹配,然后它捕获undef值而不是子字符串。另外,请注意,只要有分隔符(即,每当发生拆分时)都会产生任何此类附加字段,并且这样的附加字段不计入LIMIT。

接下来是一些例子。

在Mac OS X 10.7.5上使用Perl 5.16.0进行测试。

答案 3 :(得分:1)

一种选择是使用正则表达式而不是split。这适用于您显示的两个数据集:

use strict;
use warnings;

my @array1 = ( "0", "23", "1", "4", "65", "7" );
my $k      = 1;
my $k1     = 0;

my $j      = join( '', @array1 );
my @ar = $j =~ /([$k$k1]|[^$k$k1]+)/g;
print join( ";", @ar );

输出:

0;23;1;4657

答案 4 :(得分:0)

Perl提供了一个非常强大的正则表达式替换构造,在这种情况下不需要执行split - fu和join - fu:

$string =~ s{(?:$k|$k1)\K}{;}g ;