3

私はこの小さなスクリプトを持っています:

my @list = ('R3_05_foo.txt','T3_12_foo_bar.txt','01.txt');

foreach (@list) {
    s/(\d{2}).*\.txt$/$1.txt/;
    s/^0+//;
    print $_ . "\n";
}

期待される出力は

5.txt
12.txt
1.txt

しかし、代わりに、私は得る

R3_05.txt
T3_12.txt
1.txt

最後のものは問題ありませんが、正規表現がこの場合の文字列の開始を与える理由を理解できません$1

4

4 に答える 4

3

このパターンを試す

foreach (@list) {
    s/^.*?_?(?|0(\d)|(\d{2})).*\.txt$/$1.txt/;
    print $_ . "\n";
}


説明:

(?|...()...|...()...)ここでは、単一の参照 ( $1here )に複数のキャプチャ グループを配置できるブランチ リセット機能 (ie ) を使用します。したがって、キャプチャの左側からゼロをトリミングするために 2 番目の置換を使用することは避けます。

番号の前の先頭からすべてを削除するには、次を使用します。

.*?     # all characters zero or more times 
        # ( ? -> make the * quantifier lazy to match as less as possible)
_?      # an optional underscore



先読みを追加して、次の数字がないかどうかを確認することで、2 桁しかないことを確認できることに注意してください。

s/^.*?_?(?|0(\d)|(\d{2}))(?!\d).*\.txt$/$1.txt/;

(?!\d)は数字が続かないことを意味します。

于 2013-07-23T11:46:19.880 に答える
2

ここでの問題は、置換正規表現が文字列全体をカバーしていないため、文字列の一部のみが置換されることです。しかし、単純な問題に対してかなり複雑なソリューションを使用しています。

あなたが望むのは、文字列から 2 桁を読み取り、.txtその末尾に追加することです。では、なぜそれをしないのですか?

my @list = ('R3_05_foo.txt','T3_12_foo_bar.txt','01.txt');

for (@list) {
    if (/(\d{2})/) {
        $_ = "$1.txt";
    }
}

先行ゼロ効果を克服するために、数値にゼロを追加して強制的に数値に変換できます。

$_ = 0+$1 . ".txt";
于 2013-07-23T12:08:52.667 に答える
1

問題は、あなたのs///マッチの最初の部分はあなたが思っていることですが、2 番目の部分はあなたが考えていることを置き換えていないということです。s///以前に一致したもののみを置き換えます。したがって、あなたのようなものを置き換えるにT3_は、それも一致させる必要があります。

s/.*(\d{2}).*\.txt$/$1.txt/;
于 2013-07-23T11:57:03.483 に答える