51

私は検索を構築していて、それでjavascriptオートコンプリートを使用するつもりです。私はフィンランド(フィンランド語)出身なので、ä、ö、åなどの特殊文字を扱う必要があります

ユーザーが検索入力フィールドにテキストを入力すると、テキストをデータに一致させようとします。

これは、ユーザーが「ää」などと入力した場合に正しく機能しない簡単な例です。「äl」も同じ

var title = "this is simple string with finnish word tämä on ääkköstesti älkää ihmetelkö";
// Does not work
var searchterm = "äl";

// does not work
//var searchterm = "ää";

// Works
//var searchterm = "wi";

if ( new RegExp("\\b"+searchterm, "gi").test(title) ) {
    $("#result").html("Match: ("+searchterm+"): "+title);
} else {
    $("#result").html("nothing found with term: "+searchterm);   
}

http://jsfiddle.net/7TsxB/

では、これらのä、ö、å文字をjavascript正規表現で機能させるにはどうすればよいですか?

Unicodeコードを使用する必要があると思いますが、どうすればよいですか?これらの文字のコードは次のとおりです:[\ u00C4、\ u00E4、\ u00C5、\ u00E5、\ u00D6、\ u00F6]

=>äÄåÅöÖ

4

12 に答える 12

43

\b正規表現と、文字列の先頭と通常の256バイトの範囲外の開始文字が一致する単語の境界に問題があるようです。

を使用する代わりに、を使用して\bみてください(?:^|\\s)

var title = "this is simple string with finnish word tämä on ääkköstesti älkää ihmetelkö";
// Does not work
var searchterm = "äl";

// does not work
//var searchterm = "ää";

// Works
//var searchterm = "wi";

if ( new RegExp("(?:^|\\s)"+searchterm, "gi").test(title) ) {
    $("#result").html("Match: ("+searchterm+"): "+title);
} else {
    $("#result").html("nothing found with term: "+searchterm);   
}

壊す:

(?:括弧()は、正規表現でキャプチャグループを形成します。括弧は疑問符で始まり、コロン?:は非キャプチャグループを形成します。用語をグループ化するだけです

^カレット記号は文字列の先頭と一致します

|バーは「または」演算子です。

\s空白に一致します(\\sバックスラッシュをエスケープする必要があるため、文字列のように表示されます)

)グループを閉じます

\bしたがって、単語の境界に一致し、Unicode文字には機能しない、を使用する代わりに、文字列または空白の先頭に一致する非キャプチャグループを使用します。

于 2012-05-14T20:25:43.960 に答える
21

\bJavaScript RegEx の文字クラスは、実際には単純な ASCII エンコーディングでのみ役に立ちます。とセット またはと 文字列の最初または最後との\b間の境界のショートカット コードです。これらの文字セットは、ASCII の「単語」文字のみを考慮します。ここで、はそのクラスの否定に等しく、はそのクラスの否定です。\w\W\w\w[a-zA-Z0-9_]\W

これにより、RegEx 文字クラスは、実際の言語を扱うのにほとんど役に立たなくなります。

\s検索語が空白で区切られているだけであれば、やりたいことにはうまくいくはずです。

于 2012-05-14T20:33:21.917 に答える
14

この質問は古いですが、ユニコード文字を使用した正規表現の境界のより良い解決策を見つけたと思います。XRegExp ライブラリを使用すると、これを拡張する有効な \b 境界を実装できます

XRegExp('(?=^|$|[^\\p{L}])')

結果は 4000 文字以上になりますが、かなりのパフォーマンスを発揮しているようです。

いくつかの説明: (?= ) は、開始境界または終了境界、または文字以外の Unicode 文字を探す長さゼロの先読みです。\b は何もキャプチャしないため、最も重要な考え方は先読みです。これは単に true または false です。

于 2015-09-13T21:44:52.523 に答える
7

Unicode の特定の文字セットを使用する必要がある場合は、 XRegExpを使用することをお勧めします。このライブラリの作成者は、さまざまな言語での作業を容易にするために、あらゆる種類の地域の文字セットをマップしました。

于 2012-05-14T21:23:03.810 に答える
2

\bUnicode を使用しているときに、非常に奇妙なことに気付きました。

/\bo/.test("pop"); // false (obviously)
/\bä/.test("päp"); // true (what..?)

/\Bo/.test("pop"); // true
/\Bä/.test("päp"); // false (what..?)

\bとの意味\Bが逆になっているように見えますが、非 ASCII Unicode で使用した場合のみですか? ここで何かもっと深いことが起こっているのかもしれませんが、それが何であるかはわかりません。

いずれにせよ、Unicode 文字自体ではなく、単語の境界が問題のようです。おそらく、正しく機能しているように見えるので、\b単にに置き換える必要があります。(^|[\s\\/-_&])(ただし、シンボルのリストを私のものよりも包括的にしてください。)

于 2012-05-14T20:18:55.913 に答える
1

私の考えは、フィンランド語の文字を表すコードで検索することです

new RegExp("\\b"+asciiOnly(searchterm), "gi").test(asciiOnly(title))

私の最初のアイデアはプレーンを使用することでしたencodeURIが、% 記号は正規表現を妨害するようでした。

http://jsfiddle.net/7TsxB/5/

私は、encodeURI を使用して 128 を超えるコードですべての文字をエンコードする粗い関数を作成しましたが、その % を削除し、最初に「QQ」を追加しました。これは最良のマーカーではありませんが、英数字以外を機能させることができませんでした。

于 2012-05-14T19:58:09.403 に答える
0

同様の問題がありましたが、用語の配列を置き換える必要がありました。私が見つけたすべての解決策は、テキスト内で 2 つの用語が隣り合っている場合 (境界が重なったため) 機能しませんでした。そのため、少し修正したアプローチを使用する必要がありました。

var text = "Ještě. že; \"už\" à. Fürs, 'anlässlich' že že že.";
var terms = ["à","anlässlich","Fürs","už","Ještě", "že"];
var replaced = [];
var order = 0;
for (i = 0; i < terms.length; i++) {
    terms[i] = "(^\|[ \n\r\t.,;'\"\+!?-])(" + terms[i] + ")([ \n\r\t.,;'\"\+!?-]+\|$)";
}
var re = new RegExp(terms.join("|"), "");
while (true) {
    var replacedString = "";
    text = text.replace(re, function replacer(match){
        var beginning = match.match("^[ \n\r\t.,;'\"\+!?-]+");
        if (beginning == null) beginning = "";
        var ending = match.match("[ \n\r\t.,;'\"\+!?-]+$");
        if (ending == null) ending = "";
        replacedString = match.replace(beginning,"");
        replacedString = replacedString.replace(ending,"");
        replaced.push(replacedString);
        return beginning+"{{"+order+"}}"+ending;
    });
if (replacedString == "") break;
order += 1;
}

フィドルのコードを参照してください: http://jsfiddle.net/antoninslejska/bvbLpdos/1/

正規表現は、http: //breakthebit.org/post/3446894238/word-boundaries-in-javascripts-regularから着想を得ています。

解決策がエレガントだとは言えません...

于 2015-06-24T13:07:18.280 に答える
0

質問に対する正しい答えはandrefsによって与えられます。必要なものをすべてまとめた後、より明確に書き直すだけです。

ASCII テキストの場合\b、パターンの開始と終了の両方で単語境界を照合するために使用できます。Unicode テキストを使用する場合、同じことを行うために 2 つの異なるパターンを使用する必要があります。

  • (?<=^|\P{L})メイン パターンの前の開始または単語境界の一致に使用します。
  • (?=\P{L}|$)メインパターンの後の語尾または単語境界のマッチングに使用します。
  • さらに、(?i)これらすべてのマッチングで大文字と小文字を区別しないようにするために、すべての冒頭で使用します。

したがって、結果の答えは次のとおりです(?i)(?<=^|\P{L})xxx(?=\P{L}|$)。ここで、xxx はメイン パターンです。これは(?i)\bxxx\b、ASCII テキストの場合と同等です。

コードを機能させるには、次のことを行う必要があります。

  • 検索するパターンまたは単語を変数「searchterm」に割り当てます。
  • 変数の内容をエスケープします。たとえば、 などの正規表現の予約済み特殊文字に置き換え'\'て、同じことを行います。これを行う方法に関する質問については、こちらを確認してください。'\\''\^', '\$', '\/'
  • メソッドを使用して、上記のパターンの「xxx」の場所に変数の内容を挿入しますstring.replace()
于 2020-02-12T12:14:55.780 に答える