【问题标题】:Perl how to apply a regex only on variable which has two words?Perl如何仅对有两个单词的变量应用正则表达式?
【发布时间】:2012-10-11 20:01:15
【问题描述】:

我想在只有 2 个单词的行上应用正则表达式。我的文件看起来像这样,括号中的单词之间有可变数量的空格:

Politician_name:(何塞·玛丽亚·阿兹纳尔 | 何塞·玛丽亚·阿兹纳尔 | 何塞·玛丽亚·阿兹纳尔 | 何塞·玛丽亚·阿兹纳尔 ); 政客姓名:(托尼·布莱尔 | 托尼·布莱尔 | 托尼·布莱尔 | 托尼·布莱尔);

我想有一个输出:

Politician_name:(托尼·布莱尔 | 托尼·布莱尔 | 托尼·布莱尔 | 托尼·布莱尔 | 布莱尔·托尼 | 布莱尔·托尼);

我的代码在每一行都应用了正则表达式,我得到如下错误输出:

Politician_name:(Jose Maria Aznar | jose maria aznar | José María Aznar | josé maría aznar | ma​​ria jose | Maria Jose );

这是我的代码:

use strict;
use warnings;
use Data::Dumper;
use utf8;

open(IN, $ARGV[0]) or die "Can't read file $ARGV[0]\n";
while (my $line=<IN>)
{
    my ($pol,$value) = split(/:/, $line);

    warn Dumper \$pol;
    chomp($value);
    $value=~ s/[  ]+/ /g;
    $value=~ s/\);//g;
    my $n;  
    $n = $1 if ($value =~ /\((.+?)\|/); 
    $n=~ m/(\w*)\s(\w*)/g;
    my $swapname="$2 $1";
    warn Dumper \$swapname;

    print "$pol: $value | $swapname );\n";

}
close(IN); 

我需要怎么做才能停止处理三字名称?

【问题讨论】:

  • 看起来您可能需要过滤掉列表中的duplicate 名称。您还需要一个内部循环来遍历列表中给定政治家的所有名称。一个条目可以同时包含同一个政客的双字和三字名称吗?

标签: perl


【解决方案1】:
$n=~ m/(\w*)\s(\w*)/g;   # Replace this regex with the one below

使用下面的正则表达式与$n 进行比较,并且您需要将其包含在if 中,否则您的打印将针对每个输入执行:-

my $n;  
$n = $1 if ($value =~ /\((.+?)\|/); 
if ($n =~ m/^\s*(\w+)\s(\w+)\s*$/g) {  # Notice `$` to mark the end of 2 words..
    my $swapname="$2 $1";
    warn Dumper \$swapname;

    print "$pol: $value | $swapname );\n";
}

但是,你没有考虑|之后的下一个值..你需要这样做..它只是考虑第一个值..

因此,您的输出将是:-

Politician_name: (Tony Blair |tony blair | Tony Blair | tony blair | Blair Tony )

第二个tony blair 没有被使用。您需要为此修改代码。


实际上您需要一个循环来遍历每个名​​称,以使这段代码正常工作。


更新:- 我宁愿将您的代码更改为:-

# You should always use lexical variables as file handles..
open my $fh, '<', 'D:\demo.txt' or die $!;

while (<$fh>)  # Don't need use any extra variable here.. Default to $_
{
    my ($pol,$value) = split /:/;  # Do split on $_ by default
    warn Dumper \$pol;

    chomp($value);

    $value=~ s/[  ]+/ /g;
    $value=~ s/\((.*)\);/$1/g;

    my @name = split(/\|/, $value);  # Split your string to an array

    # Filter out array to remove duplicate

    my $_ = $name[0]; 

    if (m/^\s*(\w+)\s(\w+)\s*$/g) {  

        # If first element contains 2 words, proceed with rest of the elements

        print "($value ";  # print the original string you want..

        # Append to it later on the reverse of other array elements

        foreach (@name) {
            if (m/^\s*(\w+)\s(\w+)\s*$/g) {

                my $swapname = "$2 $1";
                warn Dumper \$swapname;

                print "| $swapname ";  # Print swapnames after $value
            }
        }
        print ");\n";  # End the string..
    }
}
close($fh);

【讨论】:

  • 您可能希望在^ 之后使用\s*,并在$ 之前使用另一个\s+。间距是不稳定的,充其量。
  • 正则表达式不起作用,我收到以下错误:swapNames_regex.pl 第 34 行的语法错误,靠近 "m/^(\w+)\s(\w+)\s+$/g; "
  • 这是因为分号,我删除了它,但仍然出现错误:在 swapNames_regex.pl 的模式匹配 (m//) 中使用未初始化的值 $n 我定义了所有变量!
  • @Rohit Jain...这个正则表达式有一些东西if (m/^\s*(\w+)\s(\w+)\s*$/g)
  • 由于这个正则表达式if (m/^\s*(\w+)\s(\w+)\s*$/g),我无法运行代码
猜你喜欢
  • 2015-10-28
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多