1

依頼された作業の正規表現を作成しようとしていますが、十分に効率的にすることができません。
目的は、以下を可能な限り効率的にすることです。
目標番号 1. 文末 (ドット、3 つのドット、感嘆符など) を使用してすべてのテキストを区切ります。
Objective number 2 文字列 'em' の後に表示されるすべての数字を取得する
これは、考えられる小さな文字列とその正規表現の例です。(本当のものは本当にハッジすることができます)
正規表現: old:
(?:[^.!?:]|...)(?:(?:[^.!?:]|...)*?em (\d+))*
new:
(?:[.!?]|[.][.][.])(?:(?:[^.!?]|[.][.][.])*?\bem\b (\d+))*

文字列に対して機能します(作成したばかりです)
(最初に . を挿入します)

.Foi visto que a batalha em 1939 foi. Claro que a data que digo ser em 1939 é uma farsa. Em 1938 já (insert em 1910) não havia reis.

私が望んでいたのは、バックトラックする必要がないため、バックトラックしない正規表現を作成することです。そのようにすることで、これに必要な処理を節約できると思います.30秒から20秒、さらには10秒に短縮できます! this1 のためだけに、完了するのに 1 秒かかります。
追加:
回答のThnxが失敗しないものになりました。しかし、それでもバックトラックが多すぎます。解決策はありますか?

追加 (削除された質問の 1 つに回答するため):
残念ながら、サンプル データがありません。これを行うように依頼された人は、サンプル データも持っていないと言いますが、これは「昨日まで」行う必要があります。このテキストで可能な限り効率的に機能するものを教えていただければ、それを使用して、必要に応じてこの作業に固有の何かを隠すことができると確信しています. そうでなければ、ここでもう一度尋ねます。

4

2 に答える 2

1

質問は紛らわしいですが、2つの異なる正規表現で最もよく達成される2つの異なるタスクがあるようです。これは、あなたが望むことを実行するテスト済みのスクリプトです(私は推測しています):

<?php // test.php 20110430_1100
    // Test data.
    $text = 'Foi visto que a batalha em 1939 foi. Claro'.
        ' que a data que digo ser em 1939 é uma farsa. E'.
        'm 1938 já (insert em 1910) não havia reis.';

    // Part 1: Find all numbers after "em".
    $re1 = '/\bem\b\s*(\d+)\b/i';
    $count = preg_match_all($re1, $text, $matches);
    if ($count) $numbers = $matches[1]; // Array of number strings.
    else        $numbers = array();     // Else no numbers found.

    // Part 2: Split text into sentences.
    $re2 = '/(?<=[.!?])\s+/';
    $sentences = preg_split($re2, $text, -1, PREG_SPLIT_NO_EMPTY);

    // Print out results.
    $ncnt = count($numbers); // Count of numbers found.
    printf("There were %d numbers following \"em\".\n", $ncnt);
    for ($i = 0; $i < $ncnt; ++$i) {
        printf("  Number[%d] = %s\n", $i + 1, $numbers[$i]);
    }
    $scnt = count($sentences); // Count of sentences found.
    printf("\nThere were %d sentences found.\n", $scnt);
    for ($i = 0; $i < $scnt; ++$i) {
        printf("  Sentence[%d] = \"%s\"\n", $i + 1, $sentences[$i]);
    }
?>

これがスクリプトからの出力です。

There were 4 numbers following "em".
Number[1] = 1939
Number[2] = 1939
Number[3] = 1938
Number[4] = 1910

There were 3 sentences found.
Sentence[1] = "Foi visto que a batalha em 1939 foi."
Sentence[2] = "Claro que a data que digo ser em 1939 é uma farsa."
Sentence[3] = "Em 1938 já (insert em 1910) não havia reis."

于 2011-04-30T17:20:26.733 に答える
0

パフォーマンスについてはお答えしませんが、

  • '...' を使用して ... を一致させるべきではありませんが、'...' を使用する必要があります (そうしないと、任意の 3 文字のシーケンスに一致します)。これにより、パフォーマンスが大幅に向上する可能性があることに注意してください。
  • 私はその言語 (スペイン語) を話せませんが、"em" という単語だけに一致させたいと思います (たとえば、balahem 1930 は一致します)。
  • 「em」と番号の間にスペースが 1 つしかないと仮定しないでください: Em__1950 (_ をスペースで置き換えます) は一致しません

編集: perf について: 繰り返しブロック内の何か (.) に一致すると、エンジンはかなりの時間前後に移動します: 明示的なパターンに一致させることができれば、常にはるかに高速になります。

于 2011-04-30T08:12:44.140 に答える