[英]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's a big one!</span>
請注意,如果您在#[number]
之后的實際字符串中沒有#
符號,則可以通過使用貪婪的否定字符 class 作為第二個捕獲組來顯着提高正則表達式的性能。 #(\d+)([^#]+)
這將樣本字符串上的步數從 283 步減少到僅 16 步。
老實說,即使是像#(\d+)(.+?(?=#\d|$))
這樣的惰性模式也會以 213 個步驟處理樣本字符串。 性能可能不是一個因素,因此請使用您最喜歡閱讀的任何正則表達式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.