Perl:如何分割字符串?

4

我有一个字符串 aa:bb::cc:yy:zz,需要将它按照以下方式分割,以创建一个包含 aa:bb::ccyyzz 的数组。即从最后一个 : 开始创建两个子字符串,并将剩余部分作为数组的一个元素。最佳方法是什么?

例:

aa:bb::cc:yy:zz --> ['aa:bb::cc','yy','zz']

dd:ff:gg:dd:ee:ff:fg --> ['dd:ff:gg:dd:ee','ff','gg']

我将IP地址:端口:协议作为文件中的键进行存储,并使用“:”进行分割以获取IP、端口和协议,当IP地址限制为IPv4时,一切正常。现在我想将其移植到IPv6上,在这种情况下,IP地址包含“:”,因此我无法通过使用“:”进行分割来获取正确的IP地址。


使用标准化的[IP地址]:端口格式存储您的(IP, 端口)对会更安全。在AnyEvent::Socket模块中,parse_hostport/format_hostport函数有助于处理它。 - dolmen
5个回答

11

这个怎么样:

#!/usr/local/bin/perl 
use Data::Dump qw(dump);
use strict;
use warnings;

my $x = 'dd:ff:gg:dd:ee:ff:fg';
my @l = $x =~ /^(.*?):([^:]+):([^:]+)$/g;
dump @l;

输出:

("dd:ff:gg:dd:ee", "ff", "fg")

请注意,此代码无法处理“两个或更少的成对字符”字符串,例如“dd:ff”或“dd”。 - yko
对我来说这不是问题,因为我期望至少有3个参数。 - kumar
谢谢M42,这对我来说是完美的解决方案。 - kumar

4

这段代码可以正确处理 $string 中包含两个或以下对数的情况:

my $string = 'aa:bb::cc:yy:zz';
my @data = split /:/, $string;
if (@data > 2) {
    unshift @data, join ':', splice @data, 0, -2;
}

# $string = 'aa:bb::cc:yy:zz';
# @data contains ('aa:bb::cc', 'yy', 'zz')

# $string = 'aa:bb';
# @data contains ('aa', 'bb')

3

我会使用一个过于激进的 split 方法,然后再进行合并。我认为当你不使用复杂的正则表达式进行切割时,结果更易读。所以:

my $string = 'aa:bb::cc:yy:zz';
my @split_string = split(/:/, $string);
my @result = (join(':', @split_string[0..scalar(@split_string)-3]), $split_string[-2], $split_string[-1]);
print join(', ', @result), "\n";

给你带来的好处:
aa:bb::cc, yy, zz

在像这样索引@split_string之前,您需要对数组界限进行一些检查。


3
$ perl -wE '$_="aa:bb::cc:yy:zz"; say join "\n", split /:([^:]+):([^:]+)$/, $_;'
aa:bb::cc
yy
zz

更新:您没有提到这是用于解析IP地址。如果是,您最好尝试在CPAN上找到一个模块。


@kumar 没关系。这基本上是与 M42 相同的解决方案。 - TLP

2
$ perl -e'$_="aa:bb::cc:yy:zz"; @f=/(.*):([^:]+):(.+)/; print "$_\n" for @f'
aa:bb::cc
yy
zz

$ perl -e'$_="dd:ff:gg:dd:ee:ff:fg"; @f=/(.*):([^:]+):(.+)/; print "$_\n" for @f'
dd:ff:gg:dd:ee
ff
fg

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