簡體   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