簡體   English   中英

正則表達式替換字符串的字符以字符開頭並以兩個字符中的任何一個結尾

[英]Regex replace characters of string starts with character and end with any of two characters

嘗試匹配以#1-9開頭的字符串注意: #后跟一個從1 to 9的數字,並以#1-9 (或 not)結尾。

完整字符串: "#1Lorem Ipsum is simply dummy text#2printing and typesetting industry"

主意:

是用<span class="one">Lorem Ipsum is simply dummy text</span>替換#1Lorem Ipsum is simply dummy text

#2printing and typesetting industry<span class="two">printing and typesetting industry</span>

所以用<span class="number">和 append 替換#1-9結束標記</span>在每個末尾。

但:

假設字符串只有一個以#1-9開頭的字符串,如下所示:

"#1Lorem Ipsum is simply dummy text"如何將</span>放在末尾以關閉<span>標記。

我猜可能會使用單詞末尾的最后一個"在它之前添加結束</span>標記,因為不再有#1-9在它之前停止,但不會丟失或替換字符串的最后一個"

所以它變成: "<span class="one">Lorem Ipsum is simply dummy text</span>"

我嘗試過的正則表達式: (#[0-9])(.*?)(#|")但這僅匹配字符串的第一部分#1並忽略#2部分(參見完整字符串)

我將使用php來匹配和替換,也許使用preg_replace只需要先找到正則表達式部分的方法。

我怎樣才能做到這一點?

您正在尋找的是負面的前瞻。 它非常強大,只有當里面的匹配不匹配時才會匹配。

#([0-9])((?:(?!$|#[0-9]).)+)

這將查找 #0-9 並在另一個 #0-9 出現或行尾時結束。 消極的前瞻位是這樣的: (?!$|#[0-9]) 它說只有在它不能匹配 $ 或 #0-9 時才繼續。 您必須為每個字符處理它,因此當您不匹配它時,將下一個字符與. ,並將其全部匹配到一個捕獲組中。

鐵路圖如下:

在此處輸入圖像描述

這是使用regexper.com生成的

<?php
function convert($str) {
    static $numberNamesMap = [
        1 => 'one',
        2 => 'two',
        3 => 'three',
        4 => 'four',
        5 => 'five',
        6 => 'six',
        7 => 'seven',
        8 => 'eight',
        9 => 'nine',
    ];
    return preg_replace_callback(
        '~#([1-9])(((?!#[1-9]).)*)~',
        function($matches) use ($numberNamesMap) {
            $class = $numberNamesMap[$matches[1]];
            $htmlText = htmlentities($matches[2]);
            return "<span class=\"$class\">$htmlText</span>";
        },
        $str
    ); 
}

參考

例子

echo convert('#1Lorem Ipsum is simply dummy text');

輸出:

<span class="one">Lorem Ipsum is simply dummy text</span>
echo convert('#1Lorem Ipsum is simply dummy text#2printing and typesetting industry');

輸出:

<span class="one">Lorem Ipsum is simply dummy text</span><span class="two">printing and typesetting industry</span>
echo convert('#1Lorem Ipsum is simply dummy text#0printing and typesetting industry');

輸出:

<span class="one">Lorem Ipsum is simply dummy text#0printing and typesetting industry</span>

preg_replace_callback()是完成這項工作的正確工具。 為避免需要手動聲明數字映射數組,您可以使用NumberFormatter class。 在回調主體中使用sprintf()將有助於將數據從 html 中分離出來,並使維護更容易。

代碼:(演示

$string = '#1Lorem Ipsum is simply dummy text#2printing and typesetting industry#0nothing#35That\'s a big one!';

echo preg_replace_callback(
         '/#(\d+)((?:(?!#\d).)+)/',
         fn($m) => sprintf(
             '<span class="%s">%s</span>',
             (new NumberFormatter("en", NumberFormatter::SPELLOUT))->format($m[1]),
             htmlentities($m[2])
         ),
         $string
     );

Output:

<span class="one">Lorem Ipsum is simply dummy text</span><span class="two">printing and typesetting industry</span><span class="zero">nothing</span><span class="thirty-five">That&#039;s a big one!</span>

請注意,如果您在#[number]之后的實際字符串中沒有#符號,則可以通過使用貪婪的否定字符 class 作為第二個捕獲組來顯着提高正則表達式的性能。 #(\d+)([^#]+)這將樣本字符串上的步數從 283 步減少到僅 16 步。

老實說,即使是像#(\d+)(.+?(?=#\d|$))這樣的惰性模式也會以 213 個步驟處理樣本字符串。 性能可能不是一個因素,因此請使用您最喜歡閱讀的任何正則表達式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM