PHP正则表达式-计算单词前后的感叹号数

PHP正则表达式-计算单词前后的感叹号数,php,regex,Php,Regex,我需要帮助完善一个用PHP编写的正则表达式,用于计算单词前后出现的感叹号的数量。在这种情况下,单词可以包括空格以外的任何字符(甚至是感叹号),如下所示(我显示的是预期的“before,after”计数): 如何对正则表达式进行编码,使其在到达某个非感叹号时停止查找前一个感叹号,并在只剩下感叹号时开始计算后一个感叹号 棘手的是,当标点符号出现在单词中时。这些应该被忽略,它们被认为是单词的一部分 以下是我的位置: preg_match_all('/(!*)\b(\S+)\b(!*)/', $w,

我需要帮助完善一个用PHP编写的正则表达式,用于计算单词前后出现的感叹号的数量。在这种情况下,单词可以包括空格以外的任何字符(甚至是感叹号),如下所示(我显示的是预期的“before,after”计数):

如何对正则表达式进行编码,使其在到达某个非感叹号时停止查找前一个感叹号,并在只剩下感叹号时开始计算后一个感叹号

棘手的是,当标点符号出现在单词中时。这些应该被忽略,它们被认为是单词的一部分

以下是我的位置:

 preg_match_all('/(!*)\b(\S+)\b(!*)/', $w, $m);
$w是单词(如上所示),$m是匹配数组

例如,“!!嗨!”将导致$m等于

Array
(
    [0] => Array
        (
            [0] => !!Hi!
        )
    [1] => Array
        (
            [0] => !!
        )
    [2] => Array
        (
            [0] => Hi
        )
    [3] => Array
        (
            [0] => !
        )
)
这是正确的,我正在寻找的。但是,当标点符号开始或结束单词时,事情会被抛出,正则表达式锚“\b”不会将其识别为单词的一部分(如本练习中所定义的)。下面是一个无法解析单词“!!!!!!!!!xd.sfgdx!!!,!!”的示例

请帮助。

< P>你只需要锚(<代码> ^ /代码>开始和<代码> $< /代码>结束),基本上是中间的任何东西。有了锚,中间的
将不匹配。这可能是第一次尝试

/^(!*).*(!*)$/

这个中间的任何问题(<代码> *>代码>)是贪婪的,它将优先于最终组<代码>(!*)< /代码>。中间的任何东西都会匹配到最后,而群里什么也没有。不过修复起来很简单,只需让中间部分不贪婪即可:

/^(!*).*?(!*)$/
现在它将匹配任何
!/代码结尾)。< /P> < P>使用这个ReXPP:< /P>
preg_match_all('/^(!*)[^!]{1}.*[^!]{1}(!*)/', $w, $m);
对于您来说,示例输出包括:

Array
(
    [0] => Array
        (
            [0] => !!!!Hi!!
        )

    [1] => Array
        (
            [0] => !!!!
        )

    [2] => Array
        (
            [0] => !!
        )

)

Array
(
    [0] => Array
        (
            [0] => !!!,!ksfgfdg!jkft!!,!
        )

    [1] => Array
        (
            [0] => !!!
        )

    [2] => Array
        (
            [0] => !
        )

)

这是一个快速的非正则表达式解决方案,因为:

$test = ['!!!!Hi!!',
         '!!!!Hi',
         '!Hi!!!',
         '!easdf.kjaf!!',
         '!hjdfa!sdfk!jaf!!',
         '!,!!!!!fdgsdfg!!sdgj',
         '!!!,!ksfgfdg!jkft!!!'];

foreach($test as $str) {
    $count = $rcount = 0;
    for ($i = 0; $i < strlen($str); $i++) {
        if ($str[$i] == '!') {
            $count += 1;
            continue;
        }
        break;
    }

    for ($i = strlen($str) - 1; $i > 0; $i--) {
        if ($str[$i] == '!') {
            $rcount += 1;
            continue;
        }
        break;
    }
    echo $str . ': ' . $count . ', ' . $rcount . '<br />';
}

开始是
^
,结束是
$
为什么不创建一个禁止字符列表,并在运行奇特的正则表达式之前进行stru_替换以清理这些字符?非常感谢。这和我们希望的差不多。。。虽然如果字符串是all“!!!!!!!!!!!!!”或者字符串中的一组感叹号中只有一个字符,“…!!!!!!!!!!!N!!!!!!!!!!!…”谢谢您的帮助,它会断开。我一直在寻找一个纯粹的正则表达式解决方案,但当我不知所措时,我采纳了一些你为我所做的事情。
Array
(
    [0] => Array
        (
            [0] => !!!!Hi!!
        )

    [1] => Array
        (
            [0] => !!!!
        )

    [2] => Array
        (
            [0] => !!
        )

)

Array
(
    [0] => Array
        (
            [0] => !!!,!ksfgfdg!jkft!!,!
        )

    [1] => Array
        (
            [0] => !!!
        )

    [2] => Array
        (
            [0] => !
        )

)
$test = ['!!!!Hi!!',
         '!!!!Hi',
         '!Hi!!!',
         '!easdf.kjaf!!',
         '!hjdfa!sdfk!jaf!!',
         '!,!!!!!fdgsdfg!!sdgj',
         '!!!,!ksfgfdg!jkft!!!'];

foreach($test as $str) {
    $count = $rcount = 0;
    for ($i = 0; $i < strlen($str); $i++) {
        if ($str[$i] == '!') {
            $count += 1;
            continue;
        }
        break;
    }

    for ($i = strlen($str) - 1; $i > 0; $i--) {
        if ($str[$i] == '!') {
            $rcount += 1;
            continue;
        }
        break;
    }
    echo $str . ': ' . $count . ', ' . $rcount . '<br />';
}
!!!!Hi!!: 4, 2
!!!!Hi: 4, 0
!Hi!!!: 1, 3
!easdf.kjaf!!: 1, 2
!hjdfa!sdfk!jaf!!: 1, 2
!,!!!!!fdgsdfg!!sdgj: 1, 0
!!!,!ksfgfdg!jkft!!!: 3, 3