2014-04-10 192 views
1

好的,所以我有另一個需要幫助的問題我需要使用perl來收集txt文件中的地址,我有一個地方可以從文件中的每個單獨的故障單獲取地址。我的問題是地址延伸的多行。我可以抓住第一條線,但無論我做什麼,它都不會抓住下一條線。perl正則表達式匹配多行

示例文本文件

NAME  Sprinkle, Jonathan U ADDRESS  16887 36 St NW  
              Calgary, AB T8O 0B0 

示例文本與公寓文件

NAME  Nguyen, Michael S  ADDRESS  100A 
              8447 149 Ave NW  
              Sherwood Park, AB T6J 0Z0 

我需要能夠同時處理同一個房間號的地址以及一個房子,沒有一個房間號

我的代碼到目前爲止(這隻能搶第一行):

if (/ADDRESS/){ 
    my @arr = /ADDRESS\s*\S*\s\S*\s\S*\s\S*\s*\n\s*\S*/g or next; 
    print "$_\n" for @arr; 
} 

輸出,這讓是: ADDRESS 16887 36 St NW 然後在這裏打印不換行的信息

+0

考慮激活無論是'/ s'或'/ M'標籤 – sshashank124

+0

我已嘗試添加/平方米,但是當我這樣做的唯一的東西,它打印出來了「1」@ sshashank124 – Mitchk

+0

@Mitchk請嘗試使用格式工具讓你的文章更具吸引力和整潔 – HamZa

回答

1

注到OP:這將有助於地址像這樣的問題,如果你提供的不僅僅是一個單一的數據記錄。

但是,當我們結合兩個數據示例時,顯然NAME和ADDRESS字段是垂直對齊的。這提供了分析的一個相當簡單的方法,因爲我們基本上只需要匹配一個確切的正則表達式:

NAME  Sprinkle, Jonathan U ADDRESS  16887 36 St NW  
              Calgary, AB T8O 0B0 
NAME  Nguyen, Michael S  ADDRESS  100A 
              8447 149 Ave NW  
              Sherwood Park, AB T6J 0Z0 

使用,作爲一個基準,下面的腳本作品解析四個記錄:

use warnings; 
use strict; 

my @records; 

while (<DATA>) { 
    if (/^NAME  (.{22})ADDRESS  (.*)/) { 
     push @records, { 
      name => $1, 
      address => $2, 
     }; 

    } elsif (/^\s{43}(.*)/) { 
     $records[-1]{address} .= "\n$1"; 

    } else { 
     warn "Unknown format on $.: $_"; 
    } 
} 

# Strip extra spacing from all fields 
for (@records) { 
    for (values %$_) { 
     s/\s+$//mg; 
    } 
} 

# Output records for debugging 
use Data::Dump; 
dd \@records; 

__DATA__ 
NAME  Sprinkle, Jonathan U ADDRESS  16887 36 St NW  
              Calgary, AB T8O 0B0 
NAME  Nguyen, Michael S  ADDRESS  100A 
              8447 149 Ave NW  
              Sherwood Park, AB T6J 0Z0 
NAME  Sprinkle, Jonathan U ADDRESS  16887 36 St NW  
              Calgary, AB T8O 0B0 
NAME  Nguyen, Michael S  ADDRESS  100A 
              8447 149 Ave NW  
              Sherwood Park, AB T6J 0Z0 

輸出:

[ 
    { 
    address => "16887 36 St NW\nCalgary, AB T8O 0B0", 
    name => "Sprinkle, Jonathan U", 
    }, 
    { 
    address => "100A\n8447 149 Ave NW\nSherwood Park, AB T6J 0Z0", 
    name => "Nguyen, Michael S", 
    }, 
    { 
    address => "16887 36 St NW\nCalgary, AB T8O 0B0", 
    name => "Sprinkle, Jonathan U", 
    }, 
    { 
    address => "100A\n8447 149 Ave NW\nSherwood Park, AB T6J 0Z0", 
    name => "Nguyen, Michael S", 
    }, 
] 
0

對於初學者休息,無論你的樣品顯示多行。所以馬上我就看不到如何根據你的例子來幫助你。

大多數情況下,這將成爲默認輸入記錄分隔符的問題。這意味着Perl在處理文件時的默認行爲是一次給你一行。除非你對此有所瞭解,否則你將永遠得不到你想要的東西。

控制這是$/的變量,因此假設FILE是你的,你需要做這樣的事情打開的文件句柄:

local $/; 
my $contents = <FILE>; 

現在$contents包含您的文件的全部內容作爲一個字符串的所有嵌入"\n"。所以你會真正能夠嘗試你的比賽,因爲你有它。

+0

對不起,他們剛開始編輯時顯示了多行,它變了。我修正它以顯示文件如何顯示信息 – Mitchk

1

由於您設置的陣列等於您的最後一次模式匹配,因此您每次迭代都會得到my @arr = /ADDRESS\s*\S*\s\S*\s\S*\s\S*\s*\n\s*\S*/g or next;只有一行。您需要添加到行與push類似如下:

DATA

NAME  Sprinkle, Jonathan U ADDRESS  16887 36 St NW Calgary, AB T8O 0B0 
NAME  Nguyen, Michael S  ADDRESS  100A 8447 149 Ave NW Sherwood Park, AB T6J 0Z0 

EX:

use strict; 
use warnings; 

my @addresses; 
while ($test =~ /ADDRESS\s*([A-Za-z0-9,[:blank:]]+)/gxm) { 
    push @addresses, $1 ; 
}