2013-03-07 156 views
0

團隊如何從正則表達式中捕獲姓氏?

我已經寫了一個Perl程序來驗證姓,名和年的格式(標點符號等)的準確性。 如果特定條目不符合指定的模式,則該條目突出顯示爲固定。

例如,我輸入文件也有類似的文本行:

我的程序工作得很好,也就是說,如果任何條目並不遵循的模式,腳本生成一個錯誤。以上輸入文字不會產生任何錯誤。但是,下面的一個是錯誤的例子,因爲玫瑰AJ是缺少一個逗號玫瑰後:

NOT FOUND: <bibliomixed id="bkrmbib120">Asher, S. R., &amp; Rose A. J. (1997). Promoting children’s social-emotional adjustment with peers. In P. Salovey &amp; D. Sluyter, (Eds). <emphasis>Emotional development and emotional intelligence: Educational implications.</emphasis> New York: Basic Books.</bibliomixed> 

從我的正則表達式搜索模式,是可以捕獲所有的姓氏和一年,因此,我可以爲每行生成一個前綴文本,如下所示?

<BIB>Abdo, Afif-Abdo, Otani, Machado, 2008</BIB><bibliomixed id="bkrmbib5">Abdo, C., Afif-Abdo, J., Otani, F., &amp; Machado, A. (2008). Sexual satisfaction among patients with erectile dysfunction treated with counseling, sildenafil, or both. <emphasis>Journal of Sexual Medicine</emphasis>, <emphasis>5</emphasis>, 1720–1726.</bibliomixed> 

我的正則表達式搜索腳本如下:

while(<$INPUT_REF_XML_FH>){ 
    $line_count += 1; 
    chomp; 
    if(/ 

    # bibliomixed XML ID tag and attribute----<START> 
    <bibliomixed 
    \s+ 
    id=".*?"> 
    # bibliomixed XML ID tag and attribute----<END> 

    # --------2 OR MORE AUTHOR GROUP--------<START> 
    (?: 
    (?: 
    # pattern for surname----<START> 
    (?:(?:[\w\x{2019}|\x{0027}]+\s)+)? # surnames with spaces 
    (?:(?:[\w\x{2019}|\x{0027}]+-)+)? # surnames with hyphens 
    (?:[A-Z](?:\x{2019}|\x{0027}))? # surnames with closing single quote or apostrophe O’Leary 
    (?:St\.\s)? # pattern for St. 
    (?:\w+-\w+\s)?# pattern for McGillicuddy-De Lisi 
    (?:[\w\x{2019}|\x{0027}]+) # final surname pattern----REQUIRED 
    # pattern for surname----<END> 
    ,\s 
    # pattern for forename----<START> 
    (?: 
    (?:(?:[A-Z]\.\s)+)? #initials with periods 
    (?:[A-Z]\.-)? #initials with hyphens and periods <<Y.-C. L.>> 
    (?:(?:[A-Z]\.\s)+)? #initials with periods 
    [A-Z]\. #----REQUIRED 
    # pattern for titles....<START> 
    (?:,\s(?:Jr\.|Sr\.|II|III|IV))? 
    # pattern for titles....<END> 
    ) 
    # pattern for forename----<END> 
    ,\s)+ 
    #---------------FINAL AUTHOR GROUP SEPATOR----<START> 
    &amp;\s 
    #---------------FINAL AUTHOR GROUP SEPATOR----<END> 

    # --------2 OR MORE AUTHOR GROUP--------<END> 
    )? 

    # --------LAST AUTHOR GROUP--------<START> 

    # pattern for surname----<START> 
    (?:(?:[\w\x{2019}|\x{0027}]+\s)+)? # surnames with spaces 
    (?:(?:[\w\x{2019}|\x{0027}]+-)+)? # surnames with hyphens 
    (?:[A-Z](?:\x{2019}|\x{0027}))? # surnames with closing single quote or apostrophe O’Leary 
    (?:St\.\s)? # pattern for St. 
    (?:\w+-\w+\s)?# pattern for McGillicuddy-De Lisi 
    (?:[\w\x{2019}|\x{0027}]+) # final surname pattern----REQUIRED 
    # pattern for surname----<END> 
    ,\s 
    # pattern for forename----<START> 
    (?: 
    (?:(?:[A-Z]\.\s)+)? #initials with periods 
    (?:[A-Z]\.-)? #initials with hyphens and periods <<Y.-C. L.>> 
    (?:(?:[A-Z]\.\s)+)? #initials with periods 
    [A-Z]\. #----REQUIRED 
    # pattern for titles....<START> 
    (?:,\s(?:Jr\.|Sr\.|II|III|IV))? 
    # pattern for titles....<END> 
    ) 
    # pattern for forename----<END> 

    (?: # pattern for editor notation----<START> 
    \s\(Ed(?:s)?\.\)\. 
    )? # pattern for editor notation----<END> 

    # --------LAST AUTHOR GROUP--------<END> 
    \s 
    \(
    # pattern for a year----<START> 
    (?:[A-Za-z]+,\s)? # July, 1999 
    (?:[A-Za-z]+\s)? # July 1999 
    (?:[0-9]{4}\/)? # 1999\/2000 
    (?:\w+\s\d+,\s)?# August 18, 2003 
    (?:[0-9]{4}|in\spress|manuscript\sin\spreparation) # (1999) (in press) (manuscript in preparation)----REQUIRED 
    (?:[A-Za-z])? # 1999a 
    (?:,\s[A-Za-z]+\s[0-9]+)? # 1999, July 2 
    (?:,\s[A-Za-z]+\s[0-9]+\x{2013}[0-9]+)? # 2002, June 19–25 
    (?:,\s[A-Za-z]+)? # 1999, Spring 
    (?:,\s[A-Za-z]+\/[A-Za-z]+)? # 1999, Spring\/Winter 
    (?:,\s[A-Za-z]+-[A-Za-z]+)? # 2003, Mid-Winter 
    (?:,\s[A-Za-z]+\s[A-Za-z]+)? # 2007, Anniversary Issue 
    # pattern for a year----<END> 
    \)\. 
    /six){ 
     print $FOUND_REPORT_FH "$line_count\tFOUND: $&\n"; 
     $found_count += 1; 
    } else{ 
     print $ERROR_REPORT_FH "$line_count\tNOT FOUND: $_\n"; 
     $not_found_count += 1; 
    } 

感謝您的幫助,

炳廷

回答

0

改變此位

# pattern for surname----<END> 
    ,?\s 

這意味着現在的可選,f被白色空間所淹沒。如果姓氏是「Bunga Bunga」,它將不起作用

+0

如果我迷惑你,我很抱歉。該腳本應該捕捉到「 Asher,S. R.,& Rose A. J.(1997)。」作爲一個錯誤,它做到了!這不是我所面臨的問題。我想知道如果輸入行是例如Abdo,C.,Afif-Abdo,J.,如何添加「姓氏1,姓氏2,Surnam3,2013 」 Otani,F.,& Machado,A。(2008)。「這是捕獲所有姓氏和年份。 – 2013-03-07 19:46:04

0

所有的子模式都是非捕獲組,從(?:開始。這減少了許多因素的編譯時間,其中之一是子模式沒有被捕獲。

要捕獲一個模式,你只需要在你需要捕捉的部分周圍放置圓括號。所以你可以刪除非捕獲斷言?:或在你需要它們的地方放置零件()http://perldoc.perl.org/perlretut.html#Non-capturing-groupings

我不確定,但是從您的代碼中,我認爲您可能會嘗試使用lookahead斷言,例如,您使用空格測試姓氏,如果沒有,則使用連字符測試姓氏。這不會每次都從同一個點開始,它會匹配第一個示例或不匹配,然後向前移動以使用第二個姓氏模式測試下一個位置,然後正則表達式是否將測試第一個子模式的第二個名稱是什麼我不確定。 http://perldoc.perl.org/perlretut.html#Looking-ahead-and-looking-behind

#!usr/bin/perl 

use warnings; 
use strict; 


my $line = '123 456 7antelope89'; 

$line =~ /^(\d+\s\d+\s)?(\d+\w+\d+)?/; 

my ($ay,$be) = ($1 ? $1:'nocapture ', $2 ? $2:'nocapture '); 

print 'a: ',$ay,'b: ',$be,$/; 

undef for ($ay,$be,$1,$2); 


$line = '123 456 7bealzelope89'; 

$line =~ /(?:\d+\s\d+\s)?(?:\d+\w+\d+)?/; 

($ay,$be) = ($1 ? $1:'nocapture ', $2 ? $2:'nocapture '); 

print 'a: ',$ay,'b: ',$be,$/; 

undef for ($ay,$be,$1,$2); 


$line = '123 456 7canteloupe89'; 

$line =~ /((?:\d+\s\d+\s))?(?:\d+(\w+)\d+)?/; 

($ay,$be) = ($1 ? $1:'nocapture ', $2 ? $2:'nocapture '); 

print 'a: ',$ay,'b: ',$be,$/; 

undef for ($ay,$be,$1,$2); 

exit 0; 

爲了捕獲整個模式的第三實施例的第一模式是沒有意義的,因爲這告訴正則表達式沒有捕捉到的圖案組,同時還捕獲圖案組。這是有用的是在第二個模式,這是一個細粒度模式捕獲,因爲捕獲的模式是非捕獲組的一部分。

a: 123 456 b: 7antelope89 
a: nocapture b: nocapture 
a: 123 456 b: canteloupe 

一個小nitpic

id=".*?" 

可能會更好,因爲

id="\w*?" 

要求是_alphanumeric IIRC ID名稱。