10

正規表現を使用してテキスト行をチェックしようとしています。

1,3,4,5,8,10,12,14,19,14

ここで、数字は「、」で区切られ、負ではなく、20以下である必要があります。また、任意の数字を繰り返さないでください。これが私のパターンです。

^(?:(?:0[1-9]|[1-9]|1[0-9]|20),)*(?:0[1-9]|[1-9]|1[0-9]|20)$

しかし、それは繰り返しをチェックすることはできません。どうすれば確認できますか?

4

5 に答える 5

7

あなたがしたいことはそれほど複雑ではありません。一致した各番号の後で、この番号が文字列にもう一度出現するかどうかを確認する必要があります。

^(?:(0[1-9]|[1-9]|1[0-9]|20),(?!.*\b\1\b))*(?:0[1-9]|[1-9]|1[0-9]|20)$

それを見て、ここで正規表現でテストしてください。

C#の場合:

string[] myStrings = { "1",
    "1,2",
    "01,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20",
    "01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20",
    "01,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,5",
    "01,02,03,04,05,06,07,08,13,09,10,11,12,13,14,15,16,17,18,19,20" };

Regex reg = new Regex(
    @"^
        (?:(0[1-9]|[1-9]|1[0-9]|20),
            (?!.*\b\1\b) # Fail if the before matched number occurs once more
        )*
        (?:0[1-9]|[1-9]|1[0-9]|20)
    $",
    RegexOptions.IgnorePatternWhitespace
);

foreach (string myString in myStrings)
    Console.WriteLine("{0} {1} a valid string.",
        myString,
        reg.IsMatch(myString) ? "is" : "is not"
    );

Console.ReadLine();
于 2012-12-26T21:53:24.523 に答える
4

質問にC#とJavaの両方のタグを付けたので、ここではコードソリューションではなく、基本的な考え方を説明します。

文字列をで分割する,と、サブ文字列のリストが表示されます"1", "3" , "4", "5", "8", "10", "12", "14", "19", "14"。これで、それらをループして、それぞれを整数として解析してみることができます。それが失敗した場合、それは数字ではありませんでした。< 0そして、成功した場合は、それがまたはであるかどうかを簡単に確認できます> 20。また、以前に持っていた一連の番号を保持して、現在の番号が繰り返されているかどうかを確認することもできます。

肝心なのは、すべてに正規表現を使用しようとすべきではないということです。そして、あなたの言語要件はとにかく定期的ではありません(あなたが物事を覚えたり、物事を数える必要がある場合、それは通常定期的ではありません)。Perlベースの正規表現は通常の正規表現よりも少し多くの機能を備えていますが、ここでは十分ではありません。

正規表現としてのソリューション

コメントでおっしゃったように、1行は最大20の数字を保持するように制限されています。各数値も0から20の間に制限されているため、線が実際にどのように見えるかについては有限の可能性があります。このように、あなたは有限の言語を持っています(可能な行の数は有限です)。有限言語は正規言語のサブセットであるため、正規表現で言語を「簡単に」表現できます。

最も簡単な解決策は、考えられるすべての行をリストすることです。したがって、1行に3つの数値があり、5が最大の数値である場合(簡単にするため)、正規表現は次のようになります。

0,1,2|0,1,3|0,1,4|0,1,5|0,2,3|0,2,4|0,2,5|0,3,4|0,3,5|0,4,5|1,2,3|1,2,4|1,2,5|1,3,4|1,3,5|1,4,5|2,3,4

もちろん、それをもっと単純化することもできます(おそらくもっと):

0,(1,(2|3|4|5)|2,(3|4|5)|3,(4|5)|4,5)|1,(2,(3|4|5)|3,(4|5)|4,5)|2,(3,(4|5)|4,5)|3,4,5

しかし、ええ、言語を有限にする要件がある場合、それも定期的になりますが、必ずしもきれいであるとは限りません。そして私は、「手動」ソリューションの方がはるかに読みやすく、特に柔軟性が高いと主張します。

于 2012-12-26T20:10:07.777 に答える
2

正規表現はこれに最適なオプションではありません。数字を繰り返すにはあまりにも毛むくじゃらになります。トークン化を確認することをお勧めします。存在しないパターンを探すような単純なことでも困難です(例として、単語を含まない行に一致する正規表現を参照してください)。

文字列をcommmasで分割し、順序付きリストに追加します。C#を使用している場合:

"1,2,3,4".Split(',')

開始してからLinqを続行し、条件が満たされているかどうかを確認します。

正規表現を使用してこれを実行する必要がある場合は、コレクション検索の戻り値を反復処理することを検討してください。しかし、これは上記の解決策をほとんど購入しません。

于 2012-12-26T20:09:26.903 に答える
1
String[] numbers = input.split(",");
Set<Integer> filtered = new TreeSet();

for(String number: numbers) {
   if(!number.startsWith("-") {
      int nbr = Integer.parseInt(number);

      if(nbr < 20) {
         filtered.add(nbr);
      }
   }
}
for(int nbr: filtered) {
   System.out.print(nbr + " ");
}
于 2012-12-26T20:56:16.480 に答える
0

正規表現が必要なため、はい、\1から\9までしか移動しないため、後方参照に制限されます。したがって、ペアリングを除外する必要があります。あなたの最大の課題は、繰り返しの数字を取り除くことです。

http://www.regular-expressions.info/refadv.htmlから

と使用(?:(\d?\d),?)+(?!<regex>)て、重複がないことを確認します。使用することもできます (?(?=<regex>)true|false)

私はこのページを使って実験しました:http://www.regextester.com/

于 2012-12-26T21:00:15.923 に答える