[英]Splitting a changing string with perl
我在perl中有一堆看起来像这样的字符串:
10 NE HARRISBURG
4 E HASWELL
2 SE OAKLEY
6 SE REDBIRD
PROVO
6 W EADS
21 N HARRISON
我需要做的是删除城市名称前面的数字和字母。 我遇到的问题是各个城市之间的差异很大。 数据几乎从不相同。 是否可以删除此数据并将其保存在单独的字符串中?
尝试这个:
for my $s (@strings) {
my @fields = split /\s+/, $s, 3;
my $city = $fields[-1];
}
您可以测试数组大小以确定字段数:
my $n = @fields;
my @l = (
'10 NE HARRISBURG',
'4 E HASWELL',
'2 SE OAKLEY',
'6 SE REDBIRD',
'PROVO',
'6 W EADS',
'21 N HARRISON',
);
foreach(@l) {
my($beg, $rest) = ($_ =~ /^(\d*\s(?:[NS]|[NS]?[EW])*)?(.*)$/);
print "beg=$beg \trest=$rest\n";
}
输出:
beg=10 NE rest=HARRISBURG
beg=4 E rest=HASWELL
beg=2 SE rest=OAKLEY
beg=6 SE rest=REDBIRD
beg= rest=PROVO
beg=6 W rest=EADS
beg=21 N rest=HARRISON
对于shinjuo,如果只想运行一个字符串,则可以执行以下操作:
my($beg, $rest) = ($l[3] =~ /^(\d*\s(?:[NS]|[NS]?[EW])*)?(.*)$/);
print "beg=$beg \trest=$rest\n";
为了避免警告未初始化的值,您必须测试$ beg是否已定义:
print defined$beg?"beg=$beg\t":"", "rest=$rest\n";
看起来您总是想要split()结果中的最后一个元素。 或者,您可以使用m /(\\ S +)$ /。
我们不能假设总是有一个城市名称并且它出现在行的最后吗? 如果是这种情况,请分割线并保留其最后一部分。 这是一个划线员命令行解决方案:
perl -lne 'split ; print $_[-1]' input.txt
输出:
HARRISBURG
HASWELL
OAKLEY
REDBIRD
PROVO
EADS
HARRISON
更新1
如果您撰写的城市名称如SAN FRANCISCO(案例在下面的注释中发现),则此解决方案将不起作用。
您的输入数据来自哪里? 如果您自己生成了它,则应添加定界符。 如果有人为您生成了它,请他们用定界符重新生成它。 解析后将成为孩子的游戏。
# replace ";" for your delimiter
perl -lne 'split ";" ; print $_[-1]' input.txt
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
sub main{
my @strings = (
'10 NE HARRISBURG'
, '4 E HASWELL'
, '2 SE OAKLEY'
, '6 SE REDBIRD'
, 'PROVO'
, '6 W EADS'
, '21 N HARRISON'
, '32 SAN FRANCISCO'
, ''
, '15 NEW YORK'
, '15 NNW NEW YORK'
, '15 NW NEW YORK'
, 'NW NEW YORK'
);
my %hash;
my $count=0;
for (@strings){
if (/\d*\s*[NS]{0,2}[EW]{0,1}\s+/){
# if there was a speed / direction
$hash{$count}{wind} = $&;
$hash{$count}{city} = $';
} else {
# if there was only a city
$hash{$count}{city} = $_;
}
$count++;
}
print Dumper(\%hash);
}
main();
#!/usr/bin/perl -w
use strict;
sub main{
my @strings = (
'10 NE HARRISBURG'
, '4 E HASWELL'
, '2 SE OAKLEY'
, '6 SE REDBIRD'
, 'PROVO'
, '6 W EADS'
, '21 N HARRISON'
, '32 SAN FRANCISCO'
, '15 NEW YORK'
, '15 NNW NEW YORK'
, '15 NW NEW YORK'
, 'NW NEW YORK'
);
for my $elem (@strings){
$elem =~ s/\d*\s*[NS]{0,2}[EW]{0,1}\s+(\w*)/$1/;
}
$"="\n";
print "@strings\n";
}
main();
使用重复操作符,根据vol7ron的建议和示例进行更改。 这将去除前导数字和方向,并且如果数字或方向(或两者都缺失)不会中断。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.