我在 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的建议和示例进行更改,使用重复运算符有效。这将去掉前导数字和方向,如果数字或方向(或两者)丢失,也不会中断。