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

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

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

正規表現で文字列の否定

[トピック内 17 記事 (1 - 17 表示)]  << 0 >>

■99465 / inTopicNo.1)  正規表現で文字列の否定
  
□投稿者/ 匿名希望マン (1回)-(2022/04/14(Thu) 20:20:31)

分類:[.NET 全般] 

正規表現で、特定の文字列を否定したいと思っています。(否定先読みなどを使わずに)
例えば、「abを含まない文字列」であれば、

[^a]*|[^a]*a[^b]*

「abcを含まない文字列」であれば、

[^a]*|[^a]*a[^b]*|[^a]*a[^b]*b[^c]*

のように出来るのではないかと思っています。
https://ideone.com/fILyW4

しかし、実際に動かしてみたところ、期待通りには動きませんでした。
https://ideone.com/ahTYK9

気が向いた方、何が間違っているのか指摘していただけると嬉しいです。
よろしくお願いします。

引用返信 編集キー/
■99470 / inTopicNo.2)  Re[1]: 正規表現で文字列の否定
□投稿者/ 774RR (878回)-(2022/04/15(Fri) 09:43:28)
日本語というか設問があいまいなのでどう答えてよいか

> abを含まない文字列
a および b を含まない
a または b を含まない
ab という文字列を含まない
どれだろう?

否定先読みを使いたくない理由は?
引用返信 編集キー/
■99473 / inTopicNo.3)  Re[1]: 正規表現で文字列の否定
□投稿者/ furu (153回)-(2022/04/15(Fri) 10:48:09)
No99465 (匿名希望マン さん) に返信
> しかし、実際に動かしてみたところ、期待通りには動きませんでした。
文字列全体と比較していないから?

Regex(@"[^a]*|[^a]*a[^b]*")
  ↓↓↓
Regex(@"^[^a]*$|^[^a]*a[^b]*$")
引用返信 編集キー/
■99475 / inTopicNo.4)  Re[2]: 正規表現で文字列の否定
□投稿者/ 匿名希望マン (2回)-(2022/04/15(Fri) 14:01:38)
774RR さん、furu さん、返信ありがとうございました。
自分でも何がしたいのか分からなくなってきました...。
ことの発端は、
https://bynatures.hatenadiary.jp/entry/3317/
を読んで、「正規表現は否定を上手く表せない?」って書いてあったので、
マジかよと思い、とりあえずこのブログに書いてあったことを真似てみただけです。
もちょっと自分でも考えてみます。


No99470 (774RR さん) に返信
> 日本語というか設問があいまいなのでどう答えてよいか
>
>>abを含まない文字列
> a および b を含まない
> a または b を含まない
> ab という文字列を含まない
> どれだろう?
あいまいですみません。
「ab という文字列を含まない」ですかね。

> 否定先読みを使いたくない理由は?
元のネタのブログにxyzの否定まであったので、この方法で増やしていくと、どのくらい複雑になるのか気になったからです。
「業務上、必要に迫られたから」とかじゃなくてすみません...。単なる好奇心です。


No99473 (furu さん) に返信
> ■No99465 (匿名希望マン さん) に返信
>>しかし、実際に動かしてみたところ、期待通りには動きませんでした。
> 文字列全体と比較していないから?
>
> Regex(@"[^a]*|[^a]*a[^b]*")
>   ↓↓↓
> Regex(@"^[^a]*$|^[^a]*a[^b]*$")
なるほど。やってみたらいい線いってました。
上の正規表現だと、文字列が2文字の場合はab以外のすべてにマッチしますが、例えば acb や adb などがマッチしないようです。
acb や adb には ab という文字列は含まれてないので、マッチしてほしいところです。
引用返信 編集キー/
■99477 / inTopicNo.5)  Re[3]: 正規表現で文字列の否定
□投稿者/ shu (1276回)-(2022/04/15(Fri) 14:55:23)
2022/04/15(Fri) 14:58:52 編集(投稿者)

No99475 (匿名希望マン さん) に返信

^([^a]*a+[^b])*[^a]*a*$

でどうでしょう?
合っているかはわかりません。
引用返信 編集キー/
■99479 / inTopicNo.6)  Re[4]: 正規表現で文字列の否定
□投稿者/ 匿名希望マン (3回)-(2022/04/15(Fri) 20:27:05)
No99477 (shu さん) に返信
> 2022/04/15(Fri) 14:58:52 編集(投稿者)
>
> ■No99475 (匿名希望マン さん) に返信
>
> ^([^a]*a+[^b])*[^a]*a*$
>
> でどうでしょう?
> 合っているかはわかりません。

書き込みありがとうございます。
この場合、例えば aab などマッチしてしまいます。
https://paiza.io/projects/CwyHw0YaUq5sZtOwugg-xA
文字列 ab が含まれているので、マッチさせたくないところです。
引用返信 編集キー/
■99487 / inTopicNo.7)  Re[5]: 正規表現で文字列の否定
□投稿者/ 伝説のカレー (3回)-(2022/04/16(Sat) 17:10:12)
めちゃ難しいですね、これ
1文字ずつ位置をずらして2文字ずつマッチングできればいんでしょうけどね
先読みを使えばそれができるってことなんでしょうねー

個人的にはもう正規表現を使わずにループでマッチングしたい

引用返信 編集キー/
■99488 / inTopicNo.8)  Re[5]: 正規表現で文字列の否定
□投稿者/ 匿名希望マン (4回)-(2022/04/16(Sat) 18:01:22)
やりたいことは、
 ・文字列aを含まない文字列 → これは自明。[^a]*
 ・文字列abを含まない文字列
 ・文字列abcを含まない文字列
 ・...
っていくつか(規則性が見えるまで)求めていって、一般項(?)を求めたいのです。

...ってことで、まずは文字列abを含まない文字列を考えました。
私はあまり賢くないので、いきなり正規表現で考えると分からなくなりそうだったので、
状態遷移図を書きながら、有限オートマトンM0<Q,Σ,δ,q0,F>を構成してみました。
図を投稿できれば良いんですけど、できなさそうなので全部文字で書きます。

・状態集合Q= {0,1,2,3}
・アルファベットΣ= {a,b,c}
・初期状態q0= 0
・受理状態F= {0,1,2}
・状態遷移表δは以下。
 ┏━┳━┳━┳━┓
 ┃ ┃a┃b┃c┃
 ┣━╋━╋━╋━┫
 ┃0┃1┃2┃2┃
 ┃1┃1┃3┃0┃
 ┃2┃1┃2┃2┃
 ┗━┻━┻━┻━┛
aでもbでもない入力すべてをcとします。
いったん状態3に到達したら、必ず不受理となります。

遷移表から判断するに、状態0と状態2は等価なようです。
これらをまとめて、整理して、M1<Q,Σ,δ,q0,F>としてみました。

・Q= {0,1,2}
・Σ= {a,b,c}
・q0= 0
・F= {0,1}
・δは以下。
 ┏━┳━┳━┳━┓
 ┃ ┃a┃b┃c┃
 ┣━╋━╋━╋━┫
 ┃0┃1┃0┃0┃
 ┃1┃1┃2┃0┃
 ┗━┻━┻━┻━┛

この決定性有限オートマトンM1を、それと等価な正規表現に変換したい...。
どうすりゃ良いのかなーーー?

引用返信 編集キー/
■99489 / inTopicNo.9)  Re[6]: 正規表現で文字列の否定
□投稿者/ 伝説のカレー (4回)-(2022/04/16(Sat) 18:12:27)
No99488 (匿名希望マン さん) に返信

んーオートマトン

ググってみたらこのページに
https://stackoverflow.com/questions/406230/regular-expression-to-match-a-line-that-doesnt-contain-a-word

ここへのリンクが貼られてて
http://www.formauri.es/personal/pgimeno/misc/non-match-regex/

単語にマッチしない正規表現を自動生成してるのでどうやってるのかはわからないですけどできるっぽいですね

引用返信 編集キー/
■99491 / inTopicNo.10)  Re[7]: 正規表現で文字列の否定
□投稿者/ 匿名希望マン (5回)-(2022/04/16(Sat) 20:35:29)
No99489 (伝説のカレー さん) に返信
> ここへのリンクが貼られてて
> http://www.formauri.es/personal/pgimeno/misc/non-match-regex/

ぴゃー!!既にあるー!
やりたかった事が既に理想的な形で提供されている!!!
そりゃそうですよねー、私ごときが考えつく事は誰かがやってますよね...。
悔しいから自分は自分の思うように続けてみます!

stackoverflowの方もありがとうございます。
英語分からんけど読んでみます!
引用返信 編集キー/
■99493 / inTopicNo.11)  Re[6]: 正規表現で文字列の否定
□投稿者/ 匿名希望マン (6回)-(2022/04/17(Sun) 12:17:55)
解決はしてませんが、No99489 で教えていただいたサイトにて答えが分かるみたいなので、とりあえずこれで解決とします。
ただし、私が知りたいのは答えではなく導出する方法なので、引き続き考えながら自分のブログに書いていきたいと思います。
(ここは画像を投稿できず不便なので...)
気が向いたらこのスレッドにも追記していきます。

それでは、考えてくださった皆さん、ありがとうございました。
解決済み
引用返信 編集キー/
■99499 / inTopicNo.12)  Re[7]: 正規表現で文字列の否定
□投稿者/ shu (1277回)-(2022/04/18(Mon) 17:29:49)
2022/04/18(Mon) 17:54:04 編集(投稿者)

No99493 (匿名希望マン さん) に返信
> 解決はしてませんが、No99489 で教えていただいたサイトにて答えが分かるみたいなので、とりあえずこれで解決とします。
> ただし、私が知りたいのは答えではなく導出する方法なので、引き続き考えながら自分のブログに書いていきたいと思います。
> (ここは画像を投稿できず不便なので...)
> 気が向いたらこのスレッドにも追記していきます。
>
> それでは、考えてくださった皆さん、ありがとうございました。

[^b]のところでaも除外する必要がありました。
a+をa+aと分解した場合にa+[^b]にこれがマッチしてしまう為これを
避ける為に必要でした。


^([^a]*a+[^ab])*[^a]*a*$

ではどうでしょう?
引用返信 編集キー/
■99502 / inTopicNo.13)  Re[8]: 正規表現で文字列の否定
□投稿者/ 匿名希望マン (7回)-(2022/04/19(Tue) 22:08:55)
No99499 (shu さん) に返信
> 2022/04/18(Mon) 17:54:04 編集(投稿者)
>
> [^b]のところでaも除外する必要がありました。
> a+をa+aと分解した場合にa+[^b]にこれがマッチしてしまう為これを
> 避ける為に必要でした。
>
>
> ^([^a]*a+[^ab])*[^a]*a*$
>
> ではどうでしょう?

書き込みありがとうございます!
a-zからなる任意の2文字〜5文字で確認してみたところ、うまくいってるみたいです。
https://ideone.com/5YcFSx
↑ブラウザではタイムアウトしてしまうので、実行結果が見れません。

No99489 で教えてもらったサイトで生成した正規表現
^([^a]|a+[^ab])*a*$
と違うので、また一つ考察の材料が増えました。
感謝します!
引用返信 編集キー/
■99529 / inTopicNo.14)  Re[9]: 正規表現で文字列の否定
□投稿者/ shu (1278回)-(2022/04/22(Fri) 01:19:13)
No99502 (匿名希望マン さん) に返信

[^a] => A
a+[^ab] => B
a* => C
と置き換えて


>>^([^a]*a+[^ab])*[^a]*a*$
AAAAAABAAAAAAABAAAAAAAC
※Aの数は0以上の任意の数
※Bはあってもなくてもよい
※AAAAAAABの数は0以上の任意の数
※Cもあってもなくてもよい


> ^([^a]|a+[^ab])*a*$
ABABABABABABC
※ABの数は0以上の任意の数でABの順に並ぶ必要もない
※Aはあってもなくてもよい
※Bはあってもなくてもよい
※Cはあってもなくてもよい

となるのでどちらでも同じ文字列にマッチする
引用返信 編集キー/
■99776 / inTopicNo.15)  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?)))))))?)?$

解決済み
引用返信 編集キー/
■99777 / inTopicNo.16)  Re[11]: 正規表現で文字列の否定
□投稿者/ 匿名希望マン (9回)-(2022/05/29(Sun) 14:56:08)
No99776 (匿名希望マン さん) に返信
テスト結果はこちら https://ideone.com/Otqvqd

> でも、本当にやりたいのは、こういう単なる文字列処理ではなく、決定性有限オートマトンから正規表現へ変換するアプローチなので、そちらも悩んで頑張って作ってみます!
DFAを正規表現に変換するアルゴリズムは http://www.nue.ie.niigata-u.ac.jp/~aoto/lecture/Automata/ の「補足資料 (5)」に沿ってやればできそう!
解決済み
引用返信 編集キー/
■99841 / inTopicNo.17)  Re[12]: 正規表現で文字列の否定
□投稿者/ 匿名希望マン (10回)-(2022/06/12(Sun) 23:04:41)
自分で正規表現エンジン(という程たいそうなものではないですが)を作りつつ、
この問題を考えてみていました。

当初の興味は
 https://bynatures.hatenadiary.jp/entry/3317/ の方法でNGワードを長くしていくと、
 正規表現はどのくらい複雑になるのか?
でした。

しかし、http://www.formauri.es/personal/pgimeno/misc/non-match-regex/ を
教えてもらい、そのうち、ジェネレーターを作ることが目的になってしまいました!
楽しそうだったので。

さて、以下の二つのアプローチで正規表現を生成していました。
 @ジェネレーターのサイトの出力を解析して、正規表現を出力するメソッドを作る
 ANGワードを与えてDFAを作り、そのDFAを正規表現に変換する

@に関しては No99776 で報告しています。
Aに関してはソースコードは割愛しますが、No99777 の資料に沿って実装してみました。
No99776 と同様、正規表現を示すと以下のようになりました(先頭の5個のみ)。
 Regex01: ^[^0]*$
 Regex02: ^[^0]*0([^01][^0]*0|0)*([^01][^0]*)?|[^0]*$
 Regex03: ^[^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|([^0]*0([^01][^0]*0|0)*([^01][^0]*)?|[^0]*)$
 Regex04: ^[^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2)*(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|(([^03][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^03][^0]*)?))|([^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|([^0]*0([^01][^0]*0|0)*([^01][^0]*)?|[^0]*))$
 Regex05: ^[^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2)*3(([^04][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2)*3)*(([^04][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2)*(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|(([^03][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^03][^0]*)?))|(([^04][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|(([^04][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^04][^0]*)?)))|([^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2)*(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|(([^03][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^03][^0]*)?))|([^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|([^0]*0([^01][^0]*0|0)*([^01][^0]*)?|[^0]*)))$
この調子でRegex16を書くと、UTF-8で8MBを超えるテキストになります!
No99777 の資料のアルゴリズムを使うなら、できるだけ短い正規表現を作るように工夫しないとダメですね。
それか、改めて正規表現を短くするアルゴリズム(そんなのあるのか知らんけど)噛ますか。

【まとめ】
NGワードを長くすると、正規表現は長くなる!

最後に所感。
 ・同じDFAでも、それと等価な正規表現はたくさんあるのかー!へぇー!
 ・No99777 の資料のアルゴリズムで、できるだけ短い正規表現を得るにはどうしたらいいのかな?
 ・DFAに最簡DFAがあるように、正規表現にも最も簡潔な正規表現が定義できて、それを得るアルゴリズムあるのかな?
 ・文字列の否定は正規表現で書けたけど、正規表現の否定って正規表現で書けるのかな?

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ