0

我在 perl 中有一堆字符串,它们看起来像这样:

10 NE HARRISBURG
4 E HASWELL
2 SE OAKLEY
6 SE REDBIRD
PROVO
6 W EADS
21 N HARRISON

我需要做的是删除城市名称之前的数字和字母。我遇到的问题是它因城市而异。数据几乎不一样。是否可以删除这些数据并将其保存在单独的字符串中?

4

5 回答 5

3

试试这个:

for my $s (@strings) {
    my @fields = split /\s+/, $s, 3;
    my $city = $fields[-1];
}

您可以测试数组大小以确定字段数:

my $n = @fields;
于 2010-07-23T14:55:23.640 回答
2
my @l = (
'10 NE HARRISBURG',
'4 E HASWELL',
'2 SE OAKLEY',
'6 SE REDBIRD',
'PROVO',
'6 W EADS',
'21 N HARRISON',
);

foreach(@l) {

根据hoobs我改变了正则表达式

    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";
于 2010-07-23T14:59:07.373 回答
1

看起来你总是想要 split() 结果中的最后一个元素。或者你可以使用 m/(\S+)$/。

于 2010-07-23T14:54:31.683 回答
1

我们不能假设总是有一个城市名称并且它出现在最后一行吗?如果是这种情况,请拆分该行并保留它的最后一部分。这是一个单行命令行解决方案:

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
于 2010-07-23T14:58:52.143 回答
1

正则表达式解决方案


解决方案 1:保留所有内容(vol7ron 的电子邮件解决方案)


#!/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();  

解决方案 2:去掉不需要的东西


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

于 2010-07-23T23:59:24.183 回答