【问题标题】:extract labelled words using regex perl使用正则表达式 perl 提取标记的单词
【发布时间】:2011-11-01 19:50:05
【问题描述】:

我正在尝试使用 perl 编写正则表达式,但我需要一些帮助。 我想做的是以下,假设我有这些文本作为例子:

1- [NP some/NN text/NNP here/NNP]

我对 /NNP 标记的单词感兴趣,所以我希望我的正则表达式搜索每一行,直到找到: [NP 然后是一个空格,然后(可能找到也可能找不到)一个标有 /NN 的单词,然后是一个或多个标有 /NNP 的单词(并且会包含一些特殊字符)。

我想从每一行中提取标有 /NNP 的单词,所以结果是:

1- 此处为文字

到目前为止,我所做的是从所有示例中提取带有 /NNP 的标记词

while ($line =~ m/\s(\S*?)\/NNP/gs)
{
        my $word = $1;
        print $word." ";
} 
print "\n";

有什么想法吗?

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    首先是高尔夫:

    my @list = map { [ /(\S+)\/NNP/g ] } map { ( /\[NP ([^\]]+)]/g ) } <DATA>;
    
    • 我们取输入中的所有行
    • 我们得到'[NP...]'的所有实例
    • 对于每个实例,我们将其映射到包含 '*/NNP' 的所有实例的数组中。

    再长一点,是这样的:

    my @list;
    while ( my $line = <DATA> ) { 
        foreach my $g ( $line =~ /\[NP ([^\]]+)]/g ) { 
            push @list, [ $g =~ /(\S+)\/NNP/g ];
        }
    }
    

    转储看起来像这样:

    @list: [
             [
               'Ebd',
               'AlmEz',
               'AbrAhym'
             ],
             [
               'hAnY',
               'HjAb'
             ],
             [
               'xAld',
               'ftH',
               'Allh'
             ],
             [
               'ESAm',
               '$rf'
             ],
             [
               'AlqAhrp'
             ]
           ]
    

    (回应评论)有两种方法可以打印出我上面的结构。更标准的方式是这样的:

    use Data::Dumper ();
    say Data::Dumper->Dump( [ \@list ], [ '*list' ] );
    

    第二个是我用的:

    use Smart::Comments;
    ### @list
    

    见Smart::Comments。 (这几乎在幕后做同样的事情。)

    【讨论】:

    • @Axeman:谢谢。我是 perl 的新手,请问我如何打印 @list,当我使用它给出的普通打印时:ARRAY(0x104a1488)ARRAY(0x104a1470)。另外,如果我不想提取仅包含一个标记词 /NNP 的 `[NP AlqAhrp/NNP]` 怎么办?
    • @Daisy,休息后查看修改后的答案。
    【解决方案2】:

    也许:

        #!/usr/bin/env perl
        use strict;
        use warnings;
        while (<DATA>) {
            while ( m{(\[NP.+?\])}g ) {
            my $piece = $1;
            1 while $piece =~ m{(\w+)/NNP}g and printf "%s ",$1;
            print "\n";
            }
        }
        __DATA__
        1- [NP Almst$Ar/NN Ebd/NNP AlmEz/NNP AbrAhym/NNP] [NP Almhnds/NN hAnY/NNP HjAb/NNP]
        2- [NP xAld/NNP ftH/NNP Allh/NNP] [NP ESAm/NNP $rf/NNP] [NP AlqAhrp/NNP]
    

    然后你要求能够跳过只有一个标记词的行。为此,我可能会这样做:

    #!/usr/bin/env perl
    use strict;
    use warnings;
    my @line = ();
    while (<DATA>) {
        while ( m{(\[NP.+?\])}g ) {
            my $piece = $1;
            while ( $piece =~ m{(\w+)/NNP}g ) {
                push @line, $1;
            }
            print "@line\n", @line = () if @line && @line > 1;
        }
    }
    __DATA__
    1- [NP Almst$Ar/NN Ebd/NNP AlmEz/NNP AbrAhym/NNP] [NP Almhnds/NN hAnY/NNP HjAb/NNP]
    2- [NP xAld/NNP ftH/NNP Allh/NNP] [NP ESAm/NNP $rf/NNP] [NP AlqAhrp/NNP]
    3- [Nothing of interest here]
    

    【讨论】:

    • 谢谢,它有效,但如果我不想提取仅包含一个标记词 /NNP 的 `[NP AlqAhrp/NNP]` 怎么办?
    【解决方案3】:

    好的,已经有很多好的答案了。这是基于split的解决方案。

    use strict;
    use warnings;
    use v5.10;  # for say(), not required
    
    while (<DATA>) {
        for (grep /^\[NP /,                 # ..and keep only the NP-blocks
            split(/(\[NP [^]]*\])/, $_)) {  # Split on NP-blocks
            my @a = map { (split m(/), $_)[0] }    # ...keep first part
                grep m{/NNP\]?$},                  # ...and keep only /NNP
                split;                      # Split the NP-block on whitespace
            say "@a";
        }
    }
    
    __DATA__
    [NP Almst$Ar/NN Ebd/NNP AlmEz/NNP AbrAhym/NNP] [NP Almhnds/NN hAnY/NNP HjAb/NNP]
    [NP xAld/NNP ftH/NNP Allh/NNP] [NP ESAm/NNP $rf/NNP] [NP AlqAhrp/NNP]
    

    【讨论】:

      【解决方案4】:

      也许是这样的?

      #!/usr/bin/perl -w
      
      use strict;
      
      my $text = <<'DAISY';
      [NP Almst$Ar/NN Ebd/NNP AlmEz/NNP AbrAhym/NNP] [NP Almhnds/NN hAnY/NNP HjAb/NNP]
      [NP xAld/NNP ftH/NNP Allh/NNP] [NP ESAm/NNP $rf/NNP] [NP AlqAhrp/NNP]
      DAISY
      
      for my $tag ($text =~ /(\[NP.+?\/NNP\])/gm) {
      
          my @words = $tag =~ / (\w+)\/NNP/g;
          print "@words\n";
      }
      

      【讨论】:

        【解决方案5】:

        假设你懂一点 perl,这应该会为你指明正确的方向:

        $str = '
        1- [NP Almst$Ar/NN Ebd/NNP AlmEz/NNP AbrAhym/NNP] [NP Almhnds/NN hAnY/NNP HjAb/NNP]
        2- [NP xAld/NNP ftH/NNP Allh/NNP] [NP ESAm/NNP $rf/NNP] [NP AlqAhrp/NNP]
        ';
        
        while ($str =~ /\[NP([^\]]+)\]/g)
        {
            for ( $1 =~ /\s(\S*?)\/NNP/g)  {
                print "$_ ";
            }
            print "\n";
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-10-28
          • 1970-01-01
          • 2019-12-31
          • 1970-01-01
          • 2011-12-31
          • 1970-01-01
          相关资源
          最近更新 更多