Perl正则表达式无法正常工作

时间:2014-02-04 11:13:54

标签: regex perl

下面提到的文件用于提供对代码存储库的访问。

cat /home/user/file
@abc_dev_group = @rel_team ram_ji jack_daniel tom_alter
@DEF_release-25Apr_dev_group= @rel_team  @SDV_dev_group
@Ship_dev_group= udit_srinivasan himanshu_singhal  vishal_tripathi
@Ship_release-15Jan2010_group = @release_team
repo cust
    RW+ dev* = @And_dev_group
@And_dev_group = @rel_team  piyush_rastogi naveen_srivastava arpit_chandra

我需要在包含以@开头并以'_dev_group'结尾的字符串的行中搜索 user 例如,@Ship_dev_group

此类字符串后跟空格(可选),后跟等号(=),然后是用户名。一旦我搜索给定用户并发现该特定用户不在,我就会在该行中附加该用户的姓名。

我在下面编写了这段代码,但它似乎不起作用。实际上它对某些人有用但对其他人失败了。尝试了许多不同的变化,但无法让它适用于所有人。

use strict;
use warnings;

my ($FILE, $repo);
my $user_name = "john_doe";
my $input_file = "/home/user/file";
my @repository_list = ("abc", "DEF","Ship", "And");

open (FILE, "<", $input_file) || die "Could not open file [$input_file]: $!";
foreach my $repo (@repository_list) {
    if ( ! grep {/^\@${repo}_dev_group.*$user_name.*/} <FILE> ) {
        system ("sed -i \"s/^\\(\@${repo}_dev_group.*\\)/\\1 $user_name/\" $input_file");
    } else {
        printf "User entry already exists in file $input_file\n";
    }
}
close FILE || die "Could not close file [$input_file]: $!";

我还使用print语句查看发生了什么。它确实显示了正确的(假设)正则表达式,它也适用于命令行(Linux框)(虽然我知道bash和Perl正则表达式表现不同)但它不能通过这个脚本。

更新
该脚本现在正在运行。 :)请看下面我添加评论的行:

open (FILE, "<", $input_file) || die "Could not open file [$input_file]: $!";
@file = <FILE>; # Read into array
foreach my $repo (@repository_list) {
    if ( ! grep {/^\@${repo}_dev_group.*$user_name.*/} @file ) { # grepped the array @file
        system ("sed -i \"s/^\\(\@${repo}_dev_group.*\\)/\\1 $user_name/\" $input_file");
    } else {
        printf "User entry already exists in file $input_file\n";
    }
}
close FILE || die "Could not close file [$input_file]: $!";

为什么现在开始工作?为什么早期的方法不起作用?我现在真的很困惑。

3 个答案:

答案 0 :(得分:0)

我认为我找到了罪魁祸首:你必须使用非贪婪的量词:所以请使用.*?代替.* ...... 例如,在@And_dev_group = @rel_team piyush_rastogi naveen_srivastava arpit_chandra之类的字符串中,您有两个and次出现,因此正则表达式的贪婪程度将尽可能匹配,这不是您想要的...

答案 1 :(得分:0)

这将在每行上搜索给定的用户名,并打印包含它的行以及与该行关联的用户名组。

use strict;
use warnings;

my @file = ('@abc_dev_group = @rel_team ram_ji jack_daniel tom_alter',
'@DEF_release-25Apr_dev_group= @rel_team  @SDV_dev_group',
'@Ship_dev_group= udit_srinivasan himanshu_singhal  vishal_tripathi',
'@Ship_release-15Jan2010_group = @release_team',
'repo cust',
'    RW+ dev* = @And_dev_group',
'@And_dev_group = @rel_team  piyush_rastogi naveen_srivastava arpit_chandra');

my $user_name = 'jack_daniel';

my $capture;
foreach (@file){
    print "$_\n" if /\@.*_dev_group\s?=(.*$user_name.*)/g;
    ($capture) = $1;
}
print "$capture\n";

打印

包含用户名匹配的行:

@abc_dev_group = @rel_team ram_ji jack_daniel tom_alter

该行上的所有用户名:

 @rel_team ram_ji jack_daniel tom_alter

答案 2 :(得分:0)

my @file; #load your file here

@file = ('@abc_dev_group = @rel_team ram_ji jack_daniel tom_alter',
'@DEF_release-25Apr_dev_group= @rel_team  @SDV_dev_group',
'@Ship_dev_group= udit_srinivasan himanshu_singhal  vishal_tripathi',
'@Ship_release-15Jan2010_group = @release_team',
'repo cust',
'    RW+ dev* = @And_dev_group',
'@And_dev_group = @rel_team  piyush_rastogi naveen_srivastava arpit_chandra');

my $user_name = "john_doe";

my @new_file = (); #rewrite lines into this

foreach my $line (@file) {
  if ($line =~ /^\@.+_dev_group\s?=\s?((.+\s?)+)$/) {
    my @users = ();
    push @users, split(/\s+/, $1);
    $line .= " $user_name" unless (grep {$_ eq $user_name} @users);    
  }

  push @new_file, $line;
}

foreach my $line (@new_file) {
  print "$line\n";
}

最后一段代码将打印出来:

@abc_dev_group = @rel_team ram_ji jack_daniel tom_alter john_doe
@DEF_release-25Apr_dev_group= @rel_team  @SDV_dev_group john_doe
@Ship_dev_group= udit_srinivasan himanshu_singhal  vishal_tripathi john_doe
@Ship_release-15Jan2010_group = @release_team
repo cust
    RW+ dev* = @And_dev_group
@And_dev_group = @rel_team  piyush_rastogi naveen_srivastava arpit_chandra john_doe