0

私は文字列を持っています

$test = 'xyz45sd2-32d34-sd23-456562.abc.com'

目的は、$1 = 23 と $2 = 45 を取得することです。つまり、最後の の両側の桁数が等しくなり-ます。桁数は可変であり、必ずしも 2 であるとは限りません。

私は次のことを試しました:

$test1 =~ s/.*(\d+)-(\d+).*//;

しかし

  • $1 には 3 が含まれます
  • $2 には 456562 が含まれます
4

5 に答える 5

1

この正規表現を試すことができます

if($test1 =~ m/(\S+)-(\S+)-([a-z]*)(\d+)-(\d\d)(\d+).*/)
{
    print $4,"|",$5;
}

456562 からの最初の 2 ディジットだけが必要であると仮定します

于 2013-08-07T05:06:15.847 に答える
1

この他のエントリは、正規表現がカウントされないことを確認します: How to match word where count of characters same

GreatBigBore のアイデアに基づいて、カウントに上限がある場合は、or 演算子 | を試すことができます。これは、一致を見つけるための要件にのみ一致します。一致した数に応じて、一致は異なるビンになります。それらを $1 と $2 に正しく配置するのは 1 つのケースだけです。 (\d{3})-(\d{3})|(\d{2})-(\d{2})|(\d{1})-(\d{1})

ただし、結果キャプチャを $1$3$5 と $2$4$6 として連結すると、探していた 2 つの文字列を効果的に取得できます。

別のアイデアは、繰り返し操作することです。一致が失敗するまで数を増やして、文字列の検索を繰り返すことができます。 (\d{1})-(\d{1})(\d{2})-(\d{2})...

二分探索が頭に浮かび、O{ln(N)} になります。N はキャプチャの長さの上限です。

于 2013-08-07T05:44:04.687 に答える
1

理論上の答え

簡潔な答え:

あなたが探しているものは、正規表現を使用することはできません。

長い答え:

正規表現 (その名前が示すように) は正規言語(チョムスキー階層Type-3 grammars)のコンパクトな表現です。

ある種のカウント ( beginningand以外のコンテキスト情報end) を維持する式を書き出そうとしているため、正規表現を使用して探しているものは使用できません。この種の動作は、 DFA (実際にはすべての有限オートマトン)としてモデル化することはできません。a かどうかの非公式な証拠は、languageその言語を受け入れるDFAregularが存在することです。この種のコンテキスト情報はDFAでモデル化できないため、矛盾して、問題の正規表現を書くことはできません。

実用的なソリューション

my ($lhs,$rhs) = $test =~ /^[^-]+-[^-]+-([^-]+)-([^-.]+)\S+/;
# Alernatively and faster
my (undef,undef,$lhs,$rhs) = split /-/, $test;

# Rest is common, no matter how $lhs and $rhs is extracted.
my @left = reverse split //, $lhs;
my @right = split //, $rhs;

my $i;
for($i=0; exists($left[$i]) and exists($right[$i]) and $left[$i] =~ /\d/ and $right[$i] =~ /\d/ ; ++$i){}

--$i;
$lhs= join "", reverse @left[0..$i];
$rhs= join "", @right[0..$i];

print $lhs, "\t", $rhs, "\n";

編集:正規表現を使用して、 、 、およびの代わりに$lhsおよびの必要な数値部分を抽出することにより、私のソリューションを改善することができます。$rhssplitreversefor

于 2013-08-07T11:32:39.033 に答える
1

perl -e '"xyz45sd2-32d34-sd23-456562.abc.com" =~ /(\d{2})-(\d{2})\d*(?=\.)/; print "$1\n$2\n"'

于 2013-08-07T05:17:27.083 に答える