正規表現で文字列の否定⑤

文字列処理でやってみた

とりあえず ここ で以下の16個の正規表現を生成して、それらのルールを分析して、C#のメソッド作ってみたよ。

  • Regex01:文字列"0"を含まない任意の文字列とマッチする正規表現
  • Regex02:文字列"01"を含まない任意の文字列とマッチする正規表現
  • Regex03:文字列"012"を含まない任意の文字列とマッチする正規表現
  • ...
  • Regex16:文字列"0123456789ABCDEF"を含まない任意の文字列とマッチする正規表現

github.com

ちなみに、生成して分析していた正規表現は以下。
ルールが見えやすいように、正規表現の縦を合わせてるけど、実際はスペースは無いよ。

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?)))))))?)?$

DFA正規表現に変換する方針に関して

NGワードの長さが増えると状態遷移図がどう変化するかは既にパターンは見えてる。
したがって、NGワードからDFAを作って、それを正規表現に変換すれば良さそう。
なんと、それをやるためのアルゴリズムがあった。ここ の「補足資料 (5)」に沿ってやればできそう。
拙作の正規表現ライブラリに、メソッド(引数はDFA、戻り値は正規表現)として組み込んでみようと思う。