5

word単語の前または後にピリオドがあるが両方ではない単語を一致させる必要があるとしましょう。次にword、、、.wordおよびword.一致する必要がありますが、一致する.word.必要はありません。これをどのように一致させ、単語の前後に何が起こったのかをキャプチャするにはどうすればよいでしょうか?

これは単純化された例であり、より複雑なケースに拡張する必要があります。たとえば、記号.and'は単語の前後に出現する可能性がありますが、一度しか出現しません。たとえば、.word'wordword.'、および.word'は有効な一致のほんの一部ですが、一致.'word.'すべきでないものや.'word'.

上記の例は私の最優先事項ですが、追加のボーナスは、ピリオドとアポストロフィが追加される順序です。したがって'.word、 と.'wordの両方が一致する必要があります。これでうまくいくはずの1つの方法は だと思いますが\.?'?|'?\.?word、OR句のステートメントの数がシンボルの数に依存しない方法を望んでいました。

4

4 に答える 4

0

Ok。wordオカレンスが文字列の先頭または末尾にある場合を適切に処理するには、もう少し時間が必要でした。

 "(?:\.word(?:[^.]|$))|(?:(?:[^.]|^)word(?:[^.]|$))|(?:(?:[^.]|^)word\.)"

LookaheadsLookbehindsregexpと同じです(python でテスト済み):

 "(?:\.word(?:(?!\.)|$))|(?:(?:(?<!\.)|^)word(?:(?!\.)|$))|(?:(?:(?<!\.)|^)word\.)"

できます:

 re.findall(pattern(above), '.word. .word .word. word.'") // return ['.word ', ' word.'] 
于 2012-06-21T14:53:27.303 に答える
0

これは、指定した良い値と悪い値を使用して JavaScript で機能します。

var func = function (str) {
    var result = true, match, re = /^([^a-z]+)[a-z]+([^a-z]+)$/i;
    if (re.test(str)) {
        match = re.exec(str);
        re = new RegExp("[" + match[1] + "]");
        result = !re.test(match[2]);
    }
    return result;
};

ここに簡単な説明があります。文字列の文字の前後に非文字が含まれている場合、非文字が抽出され、相互にテストされます。テストの結果を否定して、単語が良いか悪いかを判断します。

str = .'word.
".'", "word", "."
/[.']/.test( "." )

このfunc関数は、文字列として単語 (スペースのない文字) を想定しています。文を確認したい場合は、スペースで区切ってから各単語を確認してください。このようなもの。

    var sentence = "What does .'words'. means?";
var words = sentence.split(/\s+/g);
    var areWordsOk;
for( var i = 0, len = words.length; i < len; i++ ){
    areWordsOk = func( words[i] );
    if( !areWordsOk ){
        throw new Error( "bad word." ); // error is thrown
    }
}

これが私のテストケースです。ライブ デモはこちら: http://jsfiddle.net/Tb68G/2 テスト ケースのソースは次のとおりです。

var func = function (str) {
    var result = true, match, re = /^([^a-z]+)[a-z]+([^a-z]+)$/i;
    if (re.test(str)) {
        match = re.exec(str);
        re = new RegExp("[" + match[1] + "]");
        result = !re.test(match[2]);
    }
    return result;
};
test("test good values", function () {
    var arr = [
        "word",
        ".word",
        "word.",
        ".word",
        "'word",
        "word.'",
        ".word'"
    ];
    var i = arr.length,
    str;
    while (i--) {
        str = arr[i];
        equal(func(str), true, str + " should be true.");
    }
});
test("test bad values", function () {
    var arr = [
        ".word.",
        ".'word.'",
        ".'word'.",
        ".'word'"
    ];
    var i = arr.length,
    str;
    while (i--) {
        str = arr[i];
        equal(func(str), false, str + " should be false.");
    }
});
于 2012-06-21T16:29:44.613 に答える
0

どの味?JavaScript の場合、これは機能するはずです。

(?:^|[^\w.'])(?=[.']*(word))(?!'*\.'*\1'*\.)(?!\.*'\.*\1\.*')([.']*)\1([.']*)

説明:

  • (?:^|[^\w.'])-wordがより大きな単語の末尾でないことを確認し、先頭の区切り文字 (.または') が存在する場合、正規表現がそれをバイパスしないようにします。

  • (?=[.']*(word\b))- が長い単語の先頭wordではなく、選択した区切り文字だけが前にあることを確認します。単語はこの時点では消費されず、グループ #1 に取り込まれただけなので、次の 2 つの先読みを固定するために使用できます。

  • (?!'*\.'*\1'*\.)- 先頭の区切り文字 (存在する場合) の前に配置されます。これにより.、単語の前に a がある場合、その後に区切り文字がないことが保証されます。

  • (?!\.*'\.*\1\.*')- これは についても同じです'

  • ([.']*)\1([.']*)- 最後に、グループ #2 と #3 の区切り文字をキャプチャして、先頭または末尾の区切り文字と共に単語を消費します。

後読みをサポートするフレーバーを使用している場合、おそらく役に立たないでしょう。ほとんどのフレーバーは、後読みで照合できるものに厳しい制限を課しているため、このタスクには役に立たなくなります。上記の JavaScript 正規表現は、おそらく最良の選択肢です。ただし、この正規表現は .NET と JGSoft で機能します。これは、完全に無制限の後読みをサポートすることがわかっている唯一のフレーバーです。

(?<=(?:\.(?<dot1>)|'(?<apos1>))*)\bword\b(?=(?:\.(?<dot2>)|'(?<apos2>))*)(?!\k<dot1>\k<dot2>|\k<apos1>\k<apos2>)

説明:

  • (?<=(?:\.(?<dot1>)|'(?<apos1>))*)- 区切り文字を逆方向にスキャンします。それぞれが一致すると、それに続く空のキャプチャ グループは、その文字が見られたことを効果的にマークします。

  • \bword\b- 単語を消費します。

  • (?=(?:\.(?<dot2>)|'(?<apos2>))*)- 後読みと同じように、より多くの区切り文字を先にスキャンし、それらをチェックします。

  • (?!\k<dot1>\k<dot2>|\k<apos1>\k<apos2>)- ドットもアポストロフィも単語の前後に現れないことを表明します。空のグループへの後方参照は文字を消費することはなく、グループが一致に参加したことをアサートするだけです。

これら 2 つのフレーバーに次いで、Java の後読みはおそらく最も柔軟ですが、バグが多いことでも有名です。最初をに変更することで、この正規表現を Java に移植できるはずですが、「明らかな最大長がない」という例外がスローされるだけです。繰り返しますが、上記の JavaScript 互換の正規表現を使用した方がよいでしょう。*{0,2}

于 2012-06-22T13:30:49.293 に答える
-1

正規表現はクールなものだと思っていました...しかし 、単純なもののような巨大な式を見て、
他の方法を使用する必要がある場合があります....

CODE ITと言います!

    int findWord(string text, string word, char ch, int startIdx = 0)
    {
        while(startIdx < text.Length)
        {
            int indexOf = text.IndexOf(word, startIdx);
            if (indexOf < 0) return -1;

            char preChar = (char) 0;
            char postChar = (char) 0;

            if (indexOf > 0)
                preChar = text[indexOf - 1];

            if (indexOf < text.Length - word.Length)
                postChar = text[indexOf + word.Length];


            if ((preChar == ch) ^ (postChar == ch))
            {
                return indexOf;
            }
            startIdx = indexOf + word.Length + 1;
        } 
    }

それほど単純ではなく、1 行を超えています :)
が、より優れたパフォーマンスを発揮し、1 ~ 2 か月後に読むと理解できるようになります。

于 2012-06-21T15:19:51.143 に答える