1

我正在尝试匹配以下格式的记录:

(-,username,domain1.co.uk)\
(-,username,domain2.co.uk)

必须使用 awk 或 perl。我正在使用 cygwin 并编写了以下代码,该代码有效并匹配上述两个条目:

awk 'BEGIN {musr="(-,username,[^)]+.co.uk)"} {if ($0~musr) print $0}' netgroup

但是,如果我尝试将这个正则表达式修改为更具体,则输出什么都不是:

第一个:匹配记录,然后是最后一个反斜杠,然后匹配换行符:

"(-,username,[^)]+.co.uk)\\$"

第二:在没有反斜杠的情况下记录后立即匹配新行:

"(-,username,[^)]+.co.uk)$"

所以我决定把script改写成perl,希望perl可以处理反斜杠和行尾符号。为此,我以这种方式使用 a2p:

echo  'BEGIN {musr="(-,username,[^)]+.co.uk)"} {if ($0~musr) print $0}' | a2p.exe 
#!/usr/bin/perl
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
    if $running_under_some_shell;
                        # this emulates #! processing on NIH machines.
                        # (remove #! line above if indigestible)

eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
                        # process any FOO=bar switches

$, = ' ';               # set output field separator
$\ = "\n";              # set output record separator

$musr = '(-,username,[^)]+.co.uk)';

while (<>) {
    chomp;      # strip record separator
    if ($_ =~ $musr) {
        print $_;
    }
}

这个生成的 perl 脚本也匹配这两个条目,但是如果我尝试将此脚本修改为更具体,我会收到以下错误:

第一个:

$musr = "(-,username,[^)]+.co.uk)\\";
Trailing \ in regex m/(-,username,[^)]+.co.uk)\/ at perlmatch.pl line 18, <> line 1.

第二:

$musr = "(-,username,[^)]+.co.uk)$";
Final $ should be \$ or $name at perlmatch.pl line 14, within string
syntax error at perlmatch.pl line 14, near "= "(-,username,[^)]+.co.uk)$""
Execution of perlmatch.pl aborted due to compilation errors.

第三:

$musr = "(-,username,[^)]+.co.uk)\$";
[the output is nothing]

我做错了什么?我的问题还指出,如果有人需要在多个平台(aix、solaris、linux)上使用脚本而不是使用 perl 应该是处理(非)GNU utils 和各种(g|n)awk 版本等更好的方法。问候

4

3 回答 3

1
(-,username,[^)]+.co.uk)\\$

这里的问题不在于行尾的反斜杠,而在于括号。括号用于分组。您需要对它们进行转义以匹配文字( )字符。您还应该转义这些点,以便它们匹配文字点而不是“任何字符”。

$ awk '/\(-,username,[^)]+\.co\.uk\)$/   {print}' netgroup 
(-,username,domain2.co.uk)
$ awk '/\(-,username,[^)]+\.co\.uk\)\\$/ {print}' netgroup 
(-,username,domain1.co.uk)\

如果你坚持使用普通的 awk 并且不使用 [gn]awk 特有的功能,那么 awk 是非常便携的。我认为比 perl 更便携。

于 2012-10-02T14:59:07.327 回答
1

您的问题来自 Perl 中的字符串引用。

$musr = "(-,username,[^)]+.co.uk)\\";创建字符串时替换\\为单个反斜杠。但是您需要将两个反斜杠传递给正则表达式。因此,您必须在创建字符串时输入四个。

$musr = "(-,username,[^)]+.co.uk)$";尝试在字符串中执行变量插值。

此外,正如 John Kugelman 所指出的,括号应该被转义。

解决方案是对正则表达式使用 Perl 的内置分隔符,而不是普通的带引号的字符串。简单的方法是将它直接放入您的循环中:

while (<>) {
    chomp;      # strip record separator
    if ($_ =~ /\(-,username,[^)]+.co.uk\)$/) {
        print $_;
    }
}

如果确实需要先将模式放入变量中,请使用特殊qr// 运算符。

my $musr = qr/\(-,username,[^)]+.co.uk\)$/;
while (<>) {
    chomp;      # strip record separator
    if ($_ =~ $musr) {
        print $_;
    }
}
于 2012-10-02T15:03:08.347 回答
0

括号必须被转义。否则,它们将表达式分组。更具体地说,在行尾匹配一个可选的反斜杠(反斜杠加倍,因为作为字符串,它们也必须被转义)。

awk 'BEGIN {musr="\\(-,username,[^)]+.co.uk\\)\\\\?$"} {if ($0~musr) print $0}' netgroup
于 2012-10-02T15:03:02.187 回答