28

私は約12万語の英語の単語のリストを持っています(基本的にその言語のすべての単語)。

*ワイルドカード文字、別名、を使用してこれらの単語を検索できる正規表現が必要?です。

いくつかの例:

  • ユーザーがを検索するとm?st*、たとえばmasterまたはmisterまたはに一致しmisteryます。
  • *indユーザーが(で終わる任意の単語)を検索すると、orまたはorindに一致します。windbindblindgrind

現在、ほとんどのユーザー(特に正規表現に慣れていないユーザー)は、これ?が正確に1文字*の代わりであり、0、1文字以上の代わりであることを知っています。これをもとに検索​​機能を構築したいです。

m?st*私の質問は次のとおりです。ユーザーが入力したもの(たとえば)を正規表現に変換するにはどうすればよいですか?

私はウェブ(明らかにこのウェブサイトを含む)を検索しました、そして私が見つけたのは私にあまりにも多くを教えようとしたチュートリアルか、いくぶん似ているが私自身の問題への答えを提供するには不十分な質問だけでした。

私が理解できたのは、に置き換える必要があるということだけでし?.。だからm?st*になりm.st*ます。しかし、何に置き換えればいいのかわかりません*

どんな助けでも大歓迎です。ありがとうございました。

PS:私は正規表現にまったく慣れていません。彼らがどれほど強力であるかは知っていますが、学ぶのが非常に難しいことも知っています。だから私はそれに時間をかけたことはありません...

4

9 に答える 9

23

面白い振る舞いが必要な場合を除いて、\w代わりに使用することをお勧めします.

.空白やその他の単語以外の記号に一致しますが、これは望ましくない場合があります。

だから私はに置き換え?\w置き換え*ます\w*

*また、少なくとも1つの文字を一致させたい場合は、代わりにそれを置き換え\w+ます。これは、それが一致することを意味しますben*が、一致bendbendingませんben-それはあなた次第であり、あなたの要件が何であるかによって異なります。

于 2012-05-09T16:58:10.827 に答える
9

このライブラリを見てください:https ://github.com/alenon/JWildcard

ワイルドカード以外のすべての部分を正規表現の引用符でラップするため、特別な文字処理は必要ありません。このワイルドカード:

"mywil?card*"

この正規表現文字列に変換されます:

"\Qmywil\E.\Qcard\E.*"

ワイルドカードを正規表現文字列に変換する場合は、次を使用します。

JWildcard.wildcardToRegex("mywil?card*");

一致を直接確認したい場合は、これを使用できます。

JWildcard.matches("mywild*", "mywildcard");

デフォルトのワイルドカードルールは「?」です。->"。"、 " "-> "。 "ですが、必要に応じて、新しいルールを定義するだけで、デフォルトの動作を変更できます。

JWildcard.wildcardToRegex(wildcard, rules, strict);

ソースを使用するか、Bintray JCenterからmavenまたはgradleを使用して直接ダウンロードできます:https ://bintray.com/yevdo/jwildcard/jwildcard

Gradleの方法:

compile 'com.yevdo:jwildcard:1.4'

Mavenの方法:

<dependency>
  <groupId>com.yevdo</groupId>
  <artifactId>jwildcard</artifactId>
  <version>1.4</version>
</dependency>
于 2018-03-27T04:53:03.103 に答える
8

?に置き換えます。._*.*

于 2012-05-09T16:54:17.163 に答える
6

ワイルドカードを正規表現に変換する方法は次のとおりです。

  1. すべての特殊文字 ([{\ ^-= $!|]})。+の前に\-を付けて、文字として一致させ、ユーザーエクスペリエンスを予期しないものにしないようにします。また、 \ Q(引用符を開始する)と\ E (引用符を終了する)で囲むこともできます。セキュリティに関する段落も参照してください。
  2. *ワイルドカードを\S*に置き換えます
  3. 交換 ?\ Sのワイルドカード?
  4. オプション:パターンの前に^を付けます-これにより、先頭との完全一致が強制されます。
  5. オプション:パターンに$を追加します-これにより、末尾との完全一致が強制されます。

    \S-スペース以外の文字を表します。これは0回以上発生します。

*または+の後に一致する文字がある場合は、気が進まない(欲張りでない)数量詞の使用を検討してください。これは、 ?を追加することで実行できます。*または+の後にこのように:\ S *?および\S* +?

セキュリティを考慮してください:ユーザーは実行するコードを送信します(正規表現も一種のコードであり、ユーザー文字列が正規表現として使用されるため)。エスケープされていない正規表現をアプリケーションの他の部分に渡すことは避け、他の方法で取得したデータをフィルタリングするためにのみ使用する必要があります。なぜなら、ユーザーがワイルドカード文字列を使用して異なる正規表現を提供することにより、コードの速度に影響を与える可能性があるためです。これは、DoS攻撃で使用される可能性があります。

同様のパターンの実行速度を示す例:

seq 1 50000000 > ~/1
du -sh ~/1
563M
time grep -P '.*' ~/1 &>/dev/null
6.65s
time grep -P '.*.*.*.*.*.*.*.*' ~/1 &>/dev/null
12.55s
time grep -P '.*..*..*..*..*.*' ~/1 &>/dev/null
31.14s
time grep -P '\S*.\S*.\S*.\S*.\S*\S*' ~/1 &>/dev/null
31.27s

。*は何にでも一致する可能性があり、通常はスペースで区切られているため、使用しないことをお勧めします。

于 2014-12-12T23:22:08.933 に答える
2

.あなたが発見したように、は任意の1文字に一致する式です。何時間も検索しているうちに、間違いなくに遭遇しました。これは、式の後に使用すると、前の式と0回以上連続して*一致する繰り返し演算子です。

したがって、あなたの意味に相当するの*は、これら2つを組み合わせることです.*。これは、「0回以上の任意の文字」を意味します。

繰り返し演算子に関する正規表現チュートリアルを参照してください。

于 2012-05-09T16:53:25.083 に答える
2
  1. すべての「?」を置き換えます '\w'の文字
  2. すべての「*」文字を「\w*」に置き換えます

'*'演算子は、前の項目'。'を繰り返します。(任意の文字)0回以上。

これは、どの単語にも「。」、「*」、および「?」が含まれていないことを前提としています。

これは良い参考資料です

http://www.regular-expressions.info/reference.html

于 2012-05-09T17:03:24.593 に答える
1

(「任意の文字の0以上」に相当する正規表現)に*置き換えます。.*

于 2012-05-09T16:53:30.463 に答える
0
function matchWild(wild,name)
{
    if (wild == '*') return true;

    wild = wild.replace(/\./g,'\\.');
    wild = wild.replace(/\?/g,'.');
    wild = wild.replace(/\\/g,'\\\\');  
    wild = wild.replace(/\//g,'\\/');
    wild = wild.replace(/\*/g,'(.+?)');

    var re = new RegExp(wild,'i');
    return re.test(name);
}
于 2014-03-22T07:36:00.083 に答える
0

これは私が使用するものです:

String wildcardToRegex(String wildcardString) {
    // The 12 is arbitrary, you may adjust it to fit your needs depending
    // on how many special characters you expect in a single pattern.
    StringBuilder sb = new StringBuilder(wildcardString.length() + 12);
    sb.append('^');
    for (int i = 0; i < wildcardString.length(); ++i) {
        char c = wildcardString.charAt(i);
        if (c == '*') {
            sb.append(".*");
        } else if (c == '?') {
            sb.append('.');
        } else if ("\\.[]{}()+-^$|".indexOf(c) >= 0) {
            sb.append('\\');
            sb.append(c);
        } else {
            sb.append(c);
        }
    }
    sb.append('$');
    return sb.toString();
}

https://stackoverflow.com/a/26228852/1808989からの特殊文字リスト。

于 2016-06-05T00:06:16.220 に答える