C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

■99776 / 10階層)  正規表現で文字列の否定
□投稿者/ 匿名希望マン (8回)-(2022/05/29(Sun) 14:48:42)
お久しぶりです。能力が足りないので、時間がかかっています。

以下計16個の正規表現
 ・文字列"0"を含まない任意の文字列とマッチする正規表現Regex01、
 ・文字列"01"を含まない任意の文字列とマッチする正規表現Regex02、
 ・文字列"012"を含まない任意の文字列とマッチする正規表現Regex03、
 ・...
 ・文字列"0123456789ABCDEF"を含まない任意の文字列とマッチする正規表現Regex16、
を例のサイトで生成して、それらのルールを分析して、C#のメソッド作ってみました。
ただし、改行文字とか対応してません。

internal static class RegexPatternGenerator
{
	public static string GenerateNegativePattern(string ngWord)
	{
		if (string.IsNullOrEmpty(ngWord))
		{
			throw new Exception();
		}

		string head = ngWord[0].ToString();
		if (ngWord.Length == 1)
		{
			return string.Format("[^{0}]*", head);
		}

		string part1 = Part1(ngWord);
		string part2 = Part2(ngWord);
		string part3 = Part3(ngWord);
		string part4 = Part4(ngWord);
		return string.Format("([^{0}]|{0}({1})*({2}))*(({3}){4})?", head, part1, part2, part3, part4);
	}

	private static string Part1(string ngWord)
	{
		if (ngWord.Length < 2)
		{
			throw new Exception();
		}

		char head = ngWord[0];
		string result = head.ToString();
		for (int i = ngWord.Length - 1; 2 <= i; i--)
		{
			result = string.Format("{0}|{1}({2})", head, ngWord[i - 1], result);
		}
		return result;
	}

	private static string Part2(string ngWord)
	{
		if (ngWord.Length < 2)
		{
			throw new Exception();
		}

		char head = ngWord[0];
		string result = string.Format("[^{0}{1}]", head, ngWord[ngWord.Length - 1]);
		for (int i = ngWord.Length - 1; 2 <= i; i--)
		{
			result = string.Format("[^{0}{1}]|{1}({2})", head, ngWord[i - 1], result);
		}
		return result;
	}

	private static string Part3(string ngWord)
	{
		if (ngWord.Length < 2)
		{
			throw new Exception();
		}
		else if (ngWord.Length == 1)
		{
			return string.Empty;
		}

		char head = ngWord[0];
		string part1 = Part1(ngWord);
		if (ngWord.Length == 2)
		{
			return string.Format("{0}*", part1);
		}
		else
		{
			return string.Format("{0}({1})*", head, part1);
		}
	}

	private static string Part4(string ngWord)
	{
		if (ngWord.Length < 2)
		{
			throw new Exception();
		}
		else if (ngWord.Length == 2)
		{
			return string.Empty;
		}

		string result = string.Format("({0})?", ngWord[ngWord.Length - 2]);
		for (int i = ngWord.Length - 1; 3 <= i; i--)
		{
			result = string.Format("({0}{1})?", ngWord[i - 2], result);
		}
		return result;
	}
}

でも、本当にやりたいのは、こういう単なる文字列処理ではなく、決定性有限オートマトンから正規表現へ変換するアプローチなので、そちらも悩んで頑張って作ってみます!
できたらまた追記します!

ちなみに、生成して分析していた正規表現は以下です。
ルールが見えやすいように、正規表現の縦を合わせていますが、実際はスペースや改行はありません。
Regex01: ^[^0]*$
Regex02: ^([^0]|0+                                                                        [^01])*                                                                                                                              0*$
Regex03: ^([^0]|0(0|10)*                                                                 ([^01]|1[^02]))*                                                                                                                     (0(0|10)*                                                                 1?)?$
Regex04: ^([^0]|0(0|1(0|20))*                                                            ([^01]|1([^02]|2[^03])))*                                                                                                            (0(0|1(0|20))*                                                            (12?)?)?$
Regex05: ^([^0]|0(0|1(0|2(0|30)))*                                                       ([^01]|1([^02]|2([^03]|3[^04]))))*                                                                                                   (0(0|1(0|2(0|30)))*                                                       (1(2?|23))?)?$
Regex06: ^([^0]|0(0|1(0|2(0|3(0|40))))*                                                  ([^01]|1([^02]|2([^03]|3([^04]|4[^05])))))*                                                                                          (0(0|1(0|2(0|3(0|40))))*                                                  (1(2?|234?))?)?$
Regex07: ^([^0]|0(0|1(0|2(0|3(0|4(0|50)))))*                                             ([^01]|1([^02]|2([^03]|3([^04]|4([^05]|5[^06]))))))*                                                                                 (0(0|1(0|2(0|3(0|4(0|50)))))*                                             (1(2?|23(4?|45)))?)?$
Regex08: ^([^0]|0(0|1(0|2(0|3(0|4(0|5(0|60))))))*                                        ([^01]|1([^02]|2([^03]|3([^04]|4([^05]|5([^06]|6[^07])))))))*                                                                        (0(0|1(0|2(0|3(0|4(0|5(0|60))))))*                                        (1(2?|23(4?|456?)))?)?$
Regex09: ^([^0]|0(0|1(0|2(0|3(0|4(0|5(0|6(0|70)))))))*                                   ([^01]|1([^02]|2([^03]|3([^04]|4([^05]|5([^06]|6([^07]|7[^08]))))))))*                                                               (0(0|1(0|2(0|3(0|4(0|5(0|6(0|70)))))))*                                   (1(2?|23(4?|45(6?|67))))?)?$
Regex10: ^([^0]|0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|80))))))))*                              ([^01]|1([^02]|2([^03]|3([^04]|4([^05]|5([^06]|6([^07]|7([^08]|8[^09])))))))))*                                                      (0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|80))))))))*                              (1(2?|23(4?|45(6?|678?))))?)?$
Regex11: ^([^0]|0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|90)))))))))*                         ([^01]|1([^02]|2([^03]|3([^04]|4([^05]|5([^06]|6([^07]|7([^08]|8([^09]|9[^0A]))))))))))*                                             (0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|90)))))))))*                         (1(2?|23(4?|45(6?|67(8?|89)))))?)?$
Regex12: ^([^0]|0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|9(0|A0))))))))))*                    ([^01]|1([^02]|2([^03]|3([^04]|4([^05]|5([^06]|6([^07]|7([^08]|8([^09]|9([^0A]|A[^0B])))))))))))*                                    (0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|9(0|A0))))))))))*                    (1(2?|23(4?|45(6?|67(8?|89A?)))))?)?$
Regex13: ^([^0]|0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|9(0|A(0|B0)))))))))))*               ([^01]|1([^02]|2([^03]|3([^04]|4([^05]|5([^06]|6([^07]|7([^08]|8([^09]|9([^0A]|A([^0B]|B[^0C]))))))))))))*                           (0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|9(0|A(0|B0)))))))))))*               (1(2?|23(4?|45(6?|67(8?|89(A?|AB))))))?)?$
Regex14: ^([^0]|0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|9(0|A(0|B(0|C0))))))))))))*          ([^01]|1([^02]|2([^03]|3([^04]|4([^05]|5([^06]|6([^07]|7([^08]|8([^09]|9([^0A]|A([^0B]|B([^0C]|C[^0D])))))))))))))*                  (0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|9(0|A(0|B(0|C0))))))))))))*          (1(2?|23(4?|45(6?|67(8?|89(A?|ABC?))))))?)?$
Regex15: ^([^0]|0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|9(0|A(0|B(0|C(0|D0)))))))))))))*     ([^01]|1([^02]|2([^03]|3([^04]|4([^05]|5([^06]|6([^07]|7([^08]|8([^09]|9([^0A]|A([^0B]|B([^0C]|C([^0D]|D[^0E]))))))))))))))*         (0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|9(0|A(0|B(0|C(0|D0)))))))))))))*     (1(2?|23(4?|45(6?|67(8?|89(A?|AB(C?|CD)))))))?)?$
Regex16: ^([^0]|0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|9(0|A(0|B(0|C(0|D(0|E0))))))))))))))*([^01]|1([^02]|2([^03]|3([^04]|4([^05]|5([^06]|6([^07]|7([^08]|8([^09]|9([^0A]|A([^0B]|B([^0C]|C([^0D]|D([^0E]|E[^0F])))))))))))))))*(0(0|1(0|2(0|3(0|4(0|5(0|6(0|7(0|8(0|9(0|A(0|B(0|C(0|D(0|E0))))))))))))))*(1(2?|23(4?|45(6?|67(8?|89(A?|AB(C?|CDE?)))))))?)?$

解決済み
編集キー/

前の記事(元になった記事) 次の記事(この記事の返信)
←Re[9]: 正規表現で文字列の否定 /shu →Re[11]: 正規表現で文字列の否定 /匿名希望マン
 
上記関連ツリー

正規表現で文字列の否定 / 匿名希望マン (22/04/14(Thu) 20:20) #99465
Re[1]: 正規表現で文字列の否定 / 774RR (22/04/15(Fri) 09:43) #99470
Re[1]: 正規表現で文字列の否定 / furu (22/04/15(Fri) 10:48) #99473
  └ Re[2]: 正規表現で文字列の否定 / 匿名希望マン (22/04/15(Fri) 14:01) #99475
    └ Re[3]: 正規表現で文字列の否定 / shu (22/04/15(Fri) 14:55) #99477
      └ Re[4]: 正規表現で文字列の否定 / 匿名希望マン (22/04/15(Fri) 20:27) #99479
        ├ Re[5]: 正規表現で文字列の否定 / 匿名希望マン (22/04/16(Sat) 18:01) #99488
        │└ Re[6]: 正規表現で文字列の否定 / 伝説のカレー (22/04/16(Sat) 18:12) #99489
        │  └ Re[7]: 正規表現で文字列の否定 / 匿名希望マン (22/04/16(Sat) 20:35) #99491
        └ Re[5]: 正規表現で文字列の否定 / 伝説のカレー (22/04/16(Sat) 17:10) #99487
          └ Re[6]: 正規表現で文字列の否定 / 匿名希望マン (22/04/17(Sun) 12:17) #99493 解決済み
            └ Re[7]: 正規表現で文字列の否定 / shu (22/04/18(Mon) 17:29) #99499
              └ Re[8]: 正規表現で文字列の否定 / 匿名希望マン (22/04/19(Tue) 22:08) #99502
                └ Re[9]: 正規表現で文字列の否定 / shu (22/04/22(Fri) 01:19) #99529
                  └ 正規表現で文字列の否定 / 匿名希望マン (22/05/29(Sun) 14:48) #99776 解決済み ←Now
                    └ Re[11]: 正規表現で文字列の否定 / 匿名希望マン (22/05/29(Sun) 14:56) #99777 解決済み
                      └ Re[12]: 正規表現で文字列の否定 / 匿名希望マン (22/06/12(Sun) 23:04) #99841 解決済み

上記ツリーを一括表示 / 上記ツリーをトピック表示
 
上記の記事へ返信