3

日付の真ん中の 2 桁を形式で解析したいdd/mm/yyだけでなく、日と月に 1 桁を許可します。

これは私が思いついたものです:

(?<=^[\d]{1,2}\/)[\d]{1,2}

1 桁または 2 桁の数字とその前に[\d]{1,2}スラッシュを付けた 1 桁または 2 桁の数字が必要です。^[\d]{1,2}\/

これは多くの組み合わせでは機能しません。私はテストしまし10/10/10た 、11/12/13など...

しかし、驚いたことに(?<=^\d\d\/)[\d]{1,2}うまくいきました。

しかし、一致した[\d]{1,2}場合も一致する必要があり\d\dますか、それとも間違っていますか?

4

4 に答える 4

13

後読みサポートについて

主要な正規表現フレーバーでは、後読みのサポートが異なります。特定の制限を課すものもあれば、まったくサポートしないものもあります。

  • Javascript: サポートされていません
  • Python: 固定長のみ
  • Java: 有限長のみ
  • .NET: 制限なし

参考文献


パイソン

\d{1,2}固定長の後読みのみがサポートされている Python では、明らかに固定長がないため、元のパターンでエラーが発生します。2 つの異なる固定長の後読みを交互に行うことで、これを「修正」できます。たとえば、次のようになります。

(?<=^\d\/)\d{1,2}|(?<=^\d\d\/)\d{1,2}

または、両方の後読みを非キャプチャ グループの代替として配置することもできます。

(?:(?<=^\d\/)|(?<=^\d\d\/))\d{1,2}

\d(括弧なしで使用できることに注意してください)。

そうは言っても、代わりにキャプチャ グループを使用する方がおそらくはるかに簡単です。

^\d{1,2}\/(\d{1,2})

findallグループが 1 つしかない場合は、グループ 1 がキャプチャしたものを返すことに注意してください。グループのキャプチャは、後読みよりも広くサポートされており、多くの場合、より読みやすいパターンにつながります (この場合のように)。

このスニペットは、上記のすべてのポイントを示しています。

p = re.compile(r'(?:(?<=^\d\/)|(?<=^\d\d\/))\d{1,2}')

print(p.findall("12/34/56"))   # "[34]"
print(p.findall("1/23/45"))    # "[23]"

p = re.compile(r'^\d{1,2}\/(\d{1,2})')

print(p.findall("12/34/56"))   # "[34]"
print(p.findall("1/23/45"))    # "[23]"

p = re.compile(r'(?<=^\d{1,2}\/)\d{1,2}')
# raise error("look-behind requires fixed-width pattern")

参考文献


ジャワ

\d{1,2}Java は有限長の後読みのみをサポートするため、元のパターンで like を使用できます。これは、次のスニペットで示されています。

    String text =
        "12/34/56 date\n" +
        "1/23/45 another date\n";

    Pattern p = Pattern.compile("(?m)(?<=^\\d{1,2}/)\\d{1,2}");
    Matcher m = p.matcher(text);
    while (m.find()) {
        System.out.println(m.group());
    } // "34", "23"

すべての行の先頭に一致するよう(?m)に埋め込まれていることに注意してください。は文字列リテラルのエスケープ文字であるため、Java ではバックスラッシュを 1 つ取得するように記述する必要があることにも注意してください。Pattern.MULTILINE^\"\\"


Cシャープ

C# は、後読みで完全な正規表現をサポートしています。+次のスニペットは、後読みで繰り返しを使用する方法を示しています。

var text = @"
1/23/45
12/34/56
123/45/67
1234/56/78
";

Regex r = new Regex(@"(?m)(?<=^\d+/)\d{1,2}");
foreach (Match m in r.Matches(text)) {
  Console.WriteLine(m);
} // "23", "34", "45", "56"

Java とは異なり、C# では@-quoted stringを使用できるため、エスケープする必要はありません\

完全を期すために、C# でグループのキャプチャ オプションを使用する方法を次に示します。

Regex r = new Regex(@"(?m)^\d+/(\d{1,2})");
foreach (Match m in r.Matches(text)) {
  Console.WriteLine("Matched [" + m + "]; month = " + m.Groups[1]);
}

前のを指定すると、次のtextように出力されます。

Matched [1/23]; month = 23
Matched [12/34]; month = 34
Matched [123/45]; month = 45
Matched [1234/56]; month = 56

関連する質問

于 2010-07-01T16:05:32.677 に答える
4

質問に記載されていない後読みを使用する特定の理由がない限り、単に全体を一致させ、代わりに興味のあるビットのみをキャプチャするのはどうですか?

JavaScript の例:

>>> /^\d{1,2}\/(\d{1,2})\/\d{1,2}$/.exec("12/12/12")[1]
"12"
于 2010-07-01T16:05:48.527 に答える
3

regular-expressions.infoを引用するには:

悪いニュースは、ほとんどの正規表現フレーバーでは、正規表現を後方に適用できないため、後読み内で正規表現を使用することを許可していないことです。したがって、正規表現エンジンは、後読みをチェックする前に、何ステップ戻るかを判断できる必要があります。

したがって、Perl や Python で使用されるものを含む多くの正規表現フレーバーでは、固定長の文字列のみが許可されます。一致の長さを事前に決定できる任意の正規表現を使用できます。これは、リテラル テキストと文字クラスを使用できることを意味します。繰り返しや任意項目はご利用いただけません。代替を使用できますが、代替のすべてのオプションが同じ長さである場合に限ります。

つまり、後読み内で可変幅の式を使用しており、正規表現エンジンがそれをサポートしていないため、正規表現は機能しません。

于 2010-07-01T16:02:06.710 に答える
2

@polygenelubricants によってリストされたものに加えて、「固定長のみ」の規則にはさらに 2 つの例外があります。PCRE (PHP、Apache などの正規表現エンジン) と鬼車 (Ruby 1.9、Textmate) では、後読みは、各代替の長さが異なる限り、各代替が異なる数の文字に一致する可能性がある代替で構成される場合があります固定されています。例えば:

(?<=\b\d\d/|\b\d/)\d{1,2}(?=/\d{2}\b)

代替は後読み部分式の最上位になければならないことに注意してください。私と同じように、次のように共通要素を除外したくなるかもしれません。

(?<=\b(?:\d\d/|\d)/)\d{1,2}(?=/\d{2}\b)

...しかし、うまくいきません。最上位レベルでは、部分式は固定長ではない単一の選択肢で構成されるようになりました。

2 番目の例外は、はるかに便利です: \KPerl と PCRE でサポートされています。それは事実上、「試合が本当にここから始まったふりをする」ことを意味します。正規表現でそれより前にあるものはすべて、肯定的な後読みとして扱われます。.NET の後読みと同様に、制限はありません。通常の正規表現に表示されるものはすべて、 の前に使用できます\K

\b\d{1,2}/\K\d{1,2}(?=/\d{2}\b)

しかし、ほとんどの場合、誰かが後読みに問題を抱えている場合、後読みを使用するべきではないことがわかります。@insin が指摘したように、この問題はキャプチャ グループを使用することでより簡単に解決できます。

EDIT: EditPad ProとPowerGrepで使用される正規表現フレーバーであるJGSoftをほとんど忘れていました。.NET と同様に、正と負の完全に無制限の後読みがあります。

于 2010-07-05T01:19:26.507 に答える