繁体   English   中英

用perl分割变化的字符串

[英]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

正则表达式解决方案


解决方案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的建议和示例进行更改。 这将去除前导数字和方向,并且如果数字或方向(或两者都缺失)不会中断。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM