簡體   English   中英

在多行上匹配一個Perl正則表達式

[英]Matching a perl regular expression over multiple lines

好的,所以我還有另一個問題需要幫助,我需要使用perl在txt文件中收集地址,我有一個地方可以從文件中的每個票證中獲取地址。 我的問題是地址延伸的多行。 我可以抓住它的第一行,但是無論我做什么,它都不會抓住下一行。

樣本文本文件

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然后它在此處打印換行符,而沒有其余信息

由於my @arr = /ADDRESS\\s*\\S*\\s\\S*\\s\\S*\\s\\S*\\s*\\n\\s*\\S*/g or next;您只能得到一行my @arr = /ADDRESS\\s*\\S*\\s\\S*\\s\\S*\\s\\S*\\s*\\n\\s*\\S*/g or next; 每次迭代時,您都將數組設置為最后一次模式匹配。 您需要通過如下所示的push送來追加到該行:

數據

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 ;
}

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",
  },
]

對於初學者,您的樣本都沒有顯示多行。 因此,根據您的示例,我立即看不到如何為您提供幫助。

盡管通常這將是默認輸入記錄分隔符的問題。 這意味着Perl在處理文件時的默認行為是一次給您一行。 除非您為此做任何事情,否則您將永遠無法獲得想要的東西。

控制它的變量是$/ ,因此假設FILE是打開的文件句柄,則需要執行以下操作:

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

現在, $contents將文件的全部$contents包含在單個字符串中,並嵌入所有"\\n" 這樣一來,您便可以實際嘗試比賽。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM