1

次の形式でレコードを照合しようとしています。

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

awkまたはperlのいずれかを使用する必要があります。私はcygwinを使用しており、上記の両方のエントリで機能し、一致する次のコードを記述しました。

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

しかし、この正規表現をより具体的に変更しようとすると、出力は何もありません。

1番目:レコードを一致させ、最後に円記号を一致させ、次に改行を一致させます。

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

2番目:バックスラッシュなしでレコードの直後に新しい行を一致させます:

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

そこで、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スクリプトも両方のエントリに一致しますが、このスクリプトをより具体的に変更しようとすると、次のエラーが発生します。

1位:

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

2番目:

$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.

3位:

$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)\\";\\文字列が作成されると、単一の円記号に置き換えられます。ただし、正規表現に2つの円記号を渡す必要があります。したがって、文字列を作成するときに4つ入力する必要があります。

$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

括弧はエスケープする必要があります。それ以外の場合は、式をグループ化します。具体的には、行末のオプションのバックスラッシュを一致させます(バックスラッシュは文字列としてエスケープする必要があるため、2倍になります)。

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