私は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 の場合、文字列を 1 つだけ実行する場合は、次のようにします。
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の提案と例で変更を加えるとうまくいきました。これにより、先頭の数字と方向が取り除かれ、数字または方向 (またはその両方) が失われても壊れません。