問題 ワイルドカードマッチングは、ワイルドカードパターンp を入力文字列sに対してテストします。 アンカー マッチングを実行し、pが s 全体に一致する場合にのみtrueを返します。
このパターンは任意の一般的な構文に基づいている可能性があります(グロビングを 参照)が、Windows プログラマーはネイティブ C ランタイムでサポートされている簡略化された構文のみを議論する傾向があります。[ 7 ] [ 8 ]
エスケープ文字は定義されていません ワイルドカード:?任意の文字がちょうど 1 回出現するのと一致します。*任意の文字が任意の回数 (0 回を含む) 出現するのと一致します。 特に断りのない限り、この記事では主にWindowsにおける問題の定式化について論じる。
意味 ゼロベースのインデックスで表すと、ワイルドカードマッチング問題は次のように再帰的に定義できます。
m 00 = ( p 0 = t 0 ) m 0 j = 間違い m 私 0 = ( p 私 − 1 = '*' ) ∧ m 私 − 1 、 0 m 私 j = { m 私 − 1 、 j − 1 のために p 私 − 1 = t j − 1 ∨ p 私 − 1 = 「?」 m 私 、 j − 1 ∨ m 私 − 1 、 j のために p 私 − 1 = '*' 間違い のために p 私 − 1 ≠ t j − 1 のために 1 ≤ 私 ≤ | p | 、 1 ≤ j ≤ | t | 。 {\displaystyle {\begin{aligned}m_{00}&=(p_{0}=t_{0})\\m_{0j}&={\text{false}}\\m_{i0}&=(p_{i-1}={\text{'*'}})\land m_{i-1,0}\\m_{ij}&={\begin{cases}m_{i-1,j-1}&{\text{for}}\;p_{i-1}=t_{j-1}\lor p_{i-1}={\text{'?'}}\\m_{i,j-1}\lor m_{i-1,j}&{\text{for}}\;p_{i-1}={\text{'*'}}\\{\text{false}}&{\text{for}}\;p_{i-1}\neq t_{j-1}\end{cases}}&&\quad {\text{for}}\;1\leq i\leq |p|,1\leq j\leq |t|.\end{aligned}}} ここで、m ij は 、パターンp を テキストtを i 文字 とj 文字でそれぞれ切り詰めた結果です。これは、リヒターのアルゴリズムとカンタトーレのコレクションにあるスニペット アルゴリズムで使用されている定式化です。 [ 9 ] [ 10 ] この説明は、レーベンシュタイン距離 に似ています。
コンピュータサイエンスにおける直接関連する問題には、以下のようなものがある。
ドントケアまたはギャップを含むパターンマッチング、?定義と同等のもののみを含むアンカーなし文字列検索。[ 11 ] [ 12 ] ワイルドカードを使用したパターンマッチングは、両方のワイルドカードに相当するものが定義された、アンカーなしの文字列検索です。柔軟なワイルドカードを使用したパターンマッチングのバリアントで長さの制限が指定されていない限り、実行時間は指数関数的になります。[ 13 ]
歴史 ワイルドカードのマッチングを行う初期のアルゴリズムは再帰 に依存することが多かったが、この手法はパフォーマンス[ 10 ] と信頼性[ 8 ] の観点から批判された。これらの点を考慮すると、ワイルドカードのマッチングには非再帰アルゴリズムが好まれるようになった。
再帰アルゴリズムと非再帰アルゴリズムの両方において、パターンマッチング操作を実行するための戦略は多岐にわたり、以下に示す様々なアルゴリズムの例からもそれが明らかです。テストケース 開発やパフォーマンス最適化の手法は、特に再帰アルゴリズムの批判者によって開発されたアルゴリズムにおいて、明らかに活用されています。
再帰アルゴリズム 再帰処理は、マッチング対象となる接尾辞が複数存在する場合に一般的に発生します。これはバックトラッキング *の一種であり、一部の正規表現マッチングツールでも行われています。
これらのアルゴリズムの一般的な形式は同じです。再帰処理では、アルゴリズムは入力を部分文字列に分割し、いずれかの部分文字列が肯定的な一致を返したときに一致が発生したとみなします。 の場合、 、、をdowild("*X", "abcX")貪欲に呼び出します。通常、機能のサポートなどの重要度の低い点と、マイナーながら非常に効果的な最適化などのより重要な点で異なります。それらのいくつかには、次のものがあります。dowild("X", "abcX")dowild("X", "bcX")dowild("X", "cX")dowild("X", "X")
過剰再帰に対する ABORT シグナル (Lars Mathiesen 1991)。残りの文字列 (パターンとテキスト) 全体を単純に再帰し、*部分文字列の 1 つが肯定的な一致を返すことを確認するのは正しいですが、テキストに多くの一致がある場合に一致を拒否すると実行時間が指数関数的に増加します*。Lars Mathiesen は戻り値を 3 つのクラス (一致、一致なし、および ABORT (アスタリスクの再帰ではまったく一致しない)) に変更しました。ABORT 値は、テキストが早すぎるタイミングで消費された場合、または別のアスタリスクの一致が失敗した場合に返され、アスタリスクの数に対して線形のパフォーマンスを保証します。(全体の複雑さは、一致させる残りの文字数に対してさらに 2 倍になります。) [ 14 ] Git/Rsync の wildmatch ABORT も無効な入力をカバーします。[ 21 ] 新しい INN uwildmat も同様です。[ 22 ] 再帰におけるアスタリスクの進行。このワイルドマッチの微調整は比較的軽微です。これは、再帰が「abcX」に対して「*X」にマッチしようとする場合に適用されます。アスタリスクの後に「X」のようなリテラルが続く場合、長さが等しい最後の比較のみがマッチを生成する可能性があることは明らかです。[ 21 ]これは、2000年のuwildmat [ 22 ] で以前に見られ、van Rossumのfnmatchではより暗黙的に見られますFNM_PATHNAME。 Martin Richter のアルゴリズムは、全体的な操作は同等であるものの、このパターンの例外です。* の場合、問題の動的計画法の定式化に従って、 いずれか のインデックスを増やすように再帰します。「ABORT」テクニックも適用可能です。[ 9 ] 典型的なパターン (Cantatore によるテスト) では、貪欲呼び出しの実装よりも遅くなります。[ 10 ]
再帰アルゴリズムは一般的に理解しやすく、ABORT修正を加えることで、最悪の場合の計算量 に関して許容できるパフォーマンスを発揮します。*を含まない文字列の場合、1対1の固定関係が存在するため、マッチングには文字列サイズに比例した時間がかかります。
非再帰アルゴリズム 再帰アルゴリズムの批判者によって、以下のような手法が開発されました。
以下は該当しません。
ジャック・ハンディの誤ったアルゴリズム[ 25 ] (失敗MATCH("*?", "xx")) 上記の反復関数は、パターン/テキストポインタの古いセットを保存し、一致が失敗した場合にそれに戻ることでバックトラッキングを実装します。カートによれば、1つの一致が成功すれば十分であるため、そのようなセットは1つだけ保存すればよいとのことです。[ 17 ]
さらに、ワイルドカードマッチングの問題は、単純なテキスト置換アプローチを使用して 正規表現 マッチングに変換できます。Thompsonの構成 のような非再帰的な正規表現マッチャーは、後方参照のサポートがないため実際にはあまり使用されていませんが、一般的にワイルドカードマッチングには同様に豊富な機能セットがありません。(実際、上記のアルゴリズムの多くは と のみをサポートしています。)Thompson NFA の Russ Cox 実装は、このような場合に簡単に変更できます。[ 26 ] Gustavo Navarro のBDM ベースの nrgrep アルゴリズムは、効率的なサフィックスを重視した、より合理化された実装を提供します。[ 27 ] 正規表現 § 実装 も参照してください。?*
参考文献 ↑ 「ワイルドカード文字」 . ScienceDirect . 2018. 2018年5月27日のオリジナルからアーカイブ。 2018年5月9日 取得 。 ↑ クイグリー、エリー (2005). UNIX シェルプログラミング クイックスタート . InformIT.com. ↑ 「MS-DOS および Windows のワイルドカード文字」 。Microsoft Developer Network Library。2018 年 5 月 31 日。 ↑ 「Apache Lucene - クエリパーサー構文」 。Apache Lucene 2.9.4 ドキュメント。2006 年。 ↑ 「SQL ワイルドカード」 。W3Schools 。 2018年。 ↑ Goyvaerts, Jan (2018). "Welcome to Regular-Expressions.info" . RegularExpressions.info. ↑ 「 ワイルド カード拡張」 。docs.microsoft.com 。2022年2月8日。 1 2 3 Krauss, Kirk (2008). "Matching Wildcards: An Algorithm" . Dr. Dobb's Journal . 1 2 3 Deadlock (2015). "Wildcard Matching Recursive Algorithm C++" . Stack Overflow . 1 2 3 4 カンタトーレ、アレッサンドロ (2003)。 「ワイルドカードマッチングアルゴリズム」 。 ↑ Iliopoulos, Costas S.; Rahman, M. Sohel (2007). "Pattern Matching Algorithms with Don't Cares" (PDF) . SOFSEM 2007: Theory and Practice of Computer Science, 33rd Conference on Current Trends in Theory and Practice of Computer Science . Harrachov, Czech Republic. S2CID 14538871 . 2019-12-17 に オリジナル (PDF)からアーカイブ済み。 ↑ Clifford, Peter; Clifford, Raphaël (2007年1月)「単純な決定論的ワイルドカードマッチング」 Information Processing Letters . 101 (2): 53–54 . doi : 10.1016/j.ipl.2006.08.002 . ↑ Wu, Xindong; Qiang, Ji-Peng; Xie, Fei (2014年9月12日). "柔軟なワイルドカードを使用したパターンマッチング". Journal of Computer Science and Technology . 29 (5): 740–750 . doi : 10.1007/s11390-014-1464-3 . S2CID 16824910 . 1 2 リッチ・ザルツ(1991)。 "wildmat.c" 。 GitHub 。 ↑ Filip (2014). "ワイルドカードを使用した文字列の比較" . Stack Overflow . ↑ Murugesan, Vignesh (2014). "WildCard Matching algorithm" . 1 2 3 Kurt, Dogan. 「ワイルドカードマッチング法」 . ↑ van Rossum, Guido (2019年11月20日). "freebsd/lib/libc/gen/fnmatch.c" . GitHub . 2019年 11月21日 取得 . ↑ "fnmatch.c" . opensource.apple.com. 1999. ↑ "fnmatch_internal.c" 。Beren Minor's Mirrors。2019年11月21日。 1 2 "git/git: wildmatch.c" . GitHub . 2020-01-20. 1 2 "uwildmat.c in trunk/lib – INN" . inn.eyrie.org . 2019年 11月27日 取得 . ↑ Krauss, Kirk (2018). "Matching Wildcards: An Improved Algorithm for Big Data" . Develop for Performance. ↑ Siler (2013). "グロブパターンマッチングの再帰的解法" . Stack Overflow . ↑ Handy, Jack (2005). "ワイルドカード文字列比較 (グロビング)" . Code Project . ↑ Cox, Ross. 「正規表現マッチングはシンプルで高速になり得る」 。 ↑ Navarro, Gonzalo (2001年11月10日). "NR-grep: 高速で柔軟なパターンマッチングツール" (PDF) . Software: Practice and Experience . 31 (13): 1265– 1312. doi : 10.1002/spe.411 . S2CID 3175806 .