duanluwei9374 2018-10-30 14:05
浏览 35
已采纳

只有当某些词语不在它之前时,才能在字符串中加粗

I have a string like this.

$dot_prod = "at the coast will reach the Douglas County coast";

I'd like this result by using a regex: at the coast will reach the Douglas County coast

Specifically, I want to bold the word "coast" and "the" but only the word coast if not preceded by the word "county" and only the word "the" if not preceded by the word "at". So, essentially I want an array of words or phrases (case-insensitive that keeps the case the word/phrase was originally in) to be bolded and then an array of words or phrases that I want to ensure are not bolded. For instance, the array of words/phrases that I want bolded are:

$bold = array("coast", "the", "pass");

and the array of words I want to ensure are unbolded are:

$unbold = array("county coast", "at the", "grants pass");

I'm able to do the bolding with this:

$bold = array("coast", "the", "pass");

$dot_prod = preg_replace("/(" . implode("|", $bold) . ")/i", "<b>$1</b>", $dot_prod);

However, I've been unsuccessful at unbolding afterwards, and I definitely couldn't figure out how to do it all in one expression. Can you offer any help please? Thank you.

  • 写回答

1条回答 默认 最新

  • duanfei1987 2018-10-30 14:15
    关注

    You may match and skip the patterns you want to "unbold" and match those you want to bold in any other context.

    Build a regex like this (I added word boundaries to match whole words, you do not have to use them probably, but that seems a good idea for your current input):

    '~\b(?:county coast|at the|grants pass)\b(*SKIP)(*F)|\b(?:coast|the|pass)\b~i'
    

    See the regex demo.

    Details

    • \b - word boundary
    • (?:county coast|at the|grants pass) - any of the alternatives
    • \b - a word boundary
    • (*SKIP)(*F) - PCRE verbs to skip the current match and proceed looking for a match from the end of the current match
    • | - or
    • \b - a word boundary
    • (?:coast|the|pass) - any of the alternatives
    • \b - a word boundary.

    The $0 in the replacement is the reference to the whole match value.

    PHP demo:

    $dot_prod = "at the coast will reach the Douglas County coast";
    $bold = array("coast", "the", "pass");
    $unbold = array("county coast", "at the", "grants pass");
    $rx = "~\b(?:" . implode("|", $unbold) . ")\b(*SKIP)(*F)|\b(?:" . implode("|", $bold) . ")\b~i";
    echo preg_replace($rx, "<b>$0</b>", $dot_prod);
    // => at the <b>coast</b> will reach <b>the</b> Douglas County coast
    

    One caveat: since your search terms can include whitespace, it is a good idea to sort the $bold and $unbold array by length in the descending order before building the pattern:

    usort($unbold, function($a, $b) { return strlen($b) - strlen($a); });
    usort($bold, function($a, $b) { return strlen($b) - strlen($a); });
    

    See another PHP demo.

    In case these items can contain special regex metachars, also use preg_quote on them.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算
  • ¥15 powerbuilder中的datawindow数据整合到新的DataWindow
  • ¥20 有人知道这种图怎么画吗?
  • ¥15 pyqt6如何引用qrc文件加载里面的的资源
  • ¥15 安卓JNI项目使用lua上的问题
  • ¥20 RL+GNN解决人员排班问题时梯度消失
  • ¥60 要数控稳压电源测试数据
  • ¥15 能帮我写下这个编程吗