简体   繁体   English

Perl正则表达式不起作用

[英]Perl regex not working

File mentioned below is used for providing access to code repository. 下面提到的文件用于提供对代码存储库的访问。

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

I need to search for user in lines that contain string starting with @ and ending with '_dev_group' For example, @Ship_dev_group 我需要在包含以@开头和以'_dev_group'结尾的字符串的行中搜索用户 ,例如, @Ship_dev_group

Such strings are followed by a space (optional), followed by an equal (=) sign and then user names. 这些字符串后跟一个空格(可选),后跟一个等号(=),然后是用户名。 Once i search for a given user and find that that particular user is absent, i append that user's name in the line. 一旦我搜索了给定的用户并发现该特定用户不存在,便在该行中追加该用户的名称。

I wrote this code below but it doesn't seem to work. 我在下面编写了此代码,但似乎没有用。 Actually it's working for some but failing for others. 实际上,它为某些人工作,但对其他人却失败。 Tried many different variations but couldn't get it working for all. 尝试了许多不同的变体,但无法使其全部正常工作。

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]: $!";

I also used print statement to see what's going on. 我还使用了print语句来查看发生了什么。 It does show the correct (supposedly) regex and it also works on command line (Linux box)(though i know bash and Perl regex behave differently) but it's not working through this script. 它确实显示了正确的(据说)正则表达式,并且还可以在命令行(Linux机器)上工作(尽管我知道bash和Perl regex的行为有所不同),但是它无法通过此脚本工作。

UPDATE: 更新:
The script is now working. 该脚本现在正在运行。 :) Please see the lines below where i have added comments: :)请查看下面我添加评论的行:

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]: $!";

Why did it start working now? 为什么现在开始工作? Why was the earlier approach not working? 为什么早期的方法不起作用? I'm really confused now. 我现在真的很困惑。

I think I found the culprit: you have to use non-greedy quantifiers: so please use .*? 我想我找到了罪魁祸首:您必须使用非贪婪量词:所以请使用.*? instead of .* ... For example, in a string like @And_dev_group = @rel_team piyush_rastogi naveen_srivastava arpit_chandra , you have two and occurrences, so the greediness of the regex will match as much as possible, which is not what you want... 而不是.* ...例如,在类似@And_dev_group = @rel_team piyush_rastogi naveen_srivastava arpit_chandra的字符串中,您有两个and出现,因此正则表达式的贪婪将尽可能地匹配,这不是您想要的。 。

This will search for a given user name on each line and print the line containing it, and the group of user names associated with that line. 这将在每一行中搜索给定的用户名,并打印包含该用户名的行以及与该行关联的用户名组。

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

prints 版画

Line containing username match: 包含用户名匹配项的行:

@abc_dev_group = @rel_team ram_ji jack_daniel tom_alter

All the user names on that line: 该行上的所有用户名:

 @rel_team ram_ji jack_daniel tom_alter
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";
}

This last piece of code will print: 最后一段代码将打印:

@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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM