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

わんくま同盟

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

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


■99776 / )  Re[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?)))))))?)?$

解決済み
返信 編集キー/


管理者用

- Child Tree -