我如何计算两个单词之间的单词数?

时间:2010-07-21 07:13:43

标签: php pcre

我如何计算两个单词之间的单词数量?

   $txt = "tükörfúrógép banana orange lime, tükörfúrógép cherry árvíztűrő orange lyon
    cat lime mac tükörfúrógép cat orange lime cat árvíztűrő
    tükörfúrógép banana orange lime
    orange lime cat árvíztűrő";

这两个词:'árvíztűrő'和'tükörfúrógép'
我需要这个回报:
tükörfúrógép樱桃árvíztűrő
tükörfúrógép猫橙色石灰猫árvíztűrő
tükörfúrógép香蕉橙石灰     橙色石灰猫árvíztűrő

现在我有这个正则表达式:

preg_match_all('@((tükörfúrógép(.*)?árvíztűrő)(árvíztűrő(.*)?tükörfúrógép))@sui',$txt,$m);

3 个答案:

答案 0 :(得分:7)

我有几点要指出:

  1. 你不能在一个正则表达式中做到这一点。正则表达式是仅向前,反向匹配顺序需要第二个正则表达式。
  2. 您使用(.*)?,但意味着 (.*?)
  3. 要获得正确的匹配,您必须确保表达式的左边界不会出现在中间。
  4. 你应该在分隔词周围加上单词边界(\b)以确保整个单词匹配。 编辑:虽然这在理论上是正确的,但它不起作用PHP中的Unicode输入。
  5. 你应该在调用preg_match_all()之前将PHP语言环境切换为匈牙利语(匈牙利语,对吧?),因为语言环境会影响被认为是单词边界的内容PHP。 编辑:\b的含义确实随所选语言环境而变化。
  6. 话虽如此,正则表达式#1是:

    (\btükörfúrógép\b)((?:(?!\1).)*?)\bárvíztűrő\b
    

    和正则表达式#2是类似的,只是用反向分隔词。

    正则表达式解释:

    (               # match group 1:
      \b            #   a word boundary
      tükörfúrógép  #   your first delimiter word
      \b            #   a word boundary
    )               # end match group 1
    (               # match group 2:
      (?:           #   non-capturing group:
        (?!         #     look-ahead:
          \1        #       must not be followed by delimiter word 1
        )           #     end look-ahead
        .           #     match any next char (includes \n with the "s" switch)
      )*?           #   end non-capturing group, repeat as often as necessary
    )               # end match group 2 (this is the one you look for)
    \b              # a word boundary
    árvíztűrő       # your second delimiter word
    \b              # a word boundary
    

    UPDATE:使用PHP的 pathetic 糟糕的Unicode字符串支持,您将被迫使用这些表达式作为\b的替换:

    $before = '(?<=^|[^\p{L}])';
    $after  = '(?=[^\p{L}]|$)';
    

    此建议取自another question

答案 1 :(得分:3)

要计算两个单词之间的单词,您可以轻松使用:

count(split(" ", "lime orange banana"));

返回带匹配和计数的数组的函数将是:

function count_between_words($text, $first, $second, $case_sensitive = false)
{
    if(!preg_match_all('/('.$first.')((?:(?!\\1).)*?)'.$second.'/s' . ($case_sensitive ? "" : "i"), preg_replace("/\\s+/", " ", $text), $results, PREG_SET_ORDER))
        return array();

    $data = array();

    foreach($results as $result)
    {
        $result[2] = trim($result[2]);
        $data[] = array("match" => $result[0], "words" => $result[2], "count" => count(split(" ", $result[2])));
    }

    return $data;
}

$result = count_between_words($txt, "tükörfúrógép", "árvíztűrő");

echo "<pre>" . print_r($result, true) . "</pre>";

结果将是:

Array
(
    [0] => Array
    (
        [match] => tükörfúrógép cherry árvíztűrő
        [words] => cherry
        [count] => 1
    )

    [1] => Array
    (
        [match] => tükörfúrógép cat orange lime cat árvíztűrő
        [words] => cat orange lime cat
        [count] => 4
    )

    [2] => Array
    (
        [match] => tükörfúrógép banana orange lime orange lime cat árvíztűrő
        [words] => banana orange lime orange lime cat
        [count] => 6
    )
)

答案 2 :(得分:1)

为什么不使用各种字符串函数写几行呢?

而不是一个巨大的,令人困惑的正则表达式?

示例:

$start = strpos($txt, 'árvíztűrő') + 9; // position of first char after 'árvíztűrő'
$end   = strpos($txt, 'tükörfúrógép', $start);
$inner = substr($txt, $start, $end - $start);
$words = preg_split("/[\s,]+/", $inner);
$num   = count($words);

当然,如果你有一些巨大的输入字符串,这将耗尽内存......