PHP Conference Japan 2024

preg_replace

(PHP 4, PHP 5, PHP 7, PHP 8)

preg_replace執行正規表示式搜尋並取代

描述

preg_replace(
    字串|陣列 $pattern,
    字串|陣列 $replacement,
    字串|陣列 $subject,
    int $limit = -1,
    int &$count = null
): 字串|陣列|null

subject 中搜尋符合 pattern 的項目,並將它們取代為 replacement

若要比對確切字串,而不是模式,請考慮使用 str_replace()str_ireplace(),而不是此函式。

參數

pattern

要搜尋的模式。它可以是字串或字串陣列。

還有一些 PCRE 修飾符可用。

replacement

要取代的字串或字串陣列。如果此參數是字串且 pattern 參數是陣列,則所有模式都將被該字串取代。如果 patternreplacement 參數都是陣列,則每個 pattern 將被對應的 replacement 取代。如果 replacement 陣列中的元素少於 pattern 陣列中的元素,則任何額外的 pattern 都將被空字串取代。

replacement 可能包含 \n$n 形式的參考,後者是較偏好的形式。每個此類參考都將被 n'th 個帶括號的模式所擷取的文字取代。n 可以是 0 到 99,而 \0$0 則是指整個模式所比對的文字。從左到右(從 1 開始)計算左括號,以取得擷取子模式的編號。請注意,字串 字面值中的反斜線可能需要轉義。

當使用替換模式,且反向參考緊隨其後的是另一個數字時(例如:在比對的模式後立即放置一個數字字面值),您不能使用熟悉的 \1 表示法來表示反向參考。例如,\11 會讓 preg_replace() 感到困惑,因為它不知道您是要 \1 反向參考,後接一個 1 字面值,還是 \11 反向參考,後接空字串。在這種情況下,解決方案是使用 ${1}1。這會建立一個獨立的 $1 反向參考,並將 1 保留為字面值。

當使用已棄用的 e 修飾符時,此函式會轉義字串中的某些字元(即 '"\ 和 NULL),這些字串會取代反向參考。這樣做是為了確保反向參考在使用單引號或雙引號時不會產生任何語法錯誤(例如,'strlen(\'$1\')+strlen("$2")')。請務必了解 PHP 的 字串語法,以確切了解已解譯的字串會如何顯示。

subject

要搜尋並取代的字串或字串陣列。

如果 subject 是陣列,則會在 subject 的每個項目上執行搜尋和取代,且傳回值也會是陣列。

如果 subject 陣列是關聯式陣列,則索引鍵會保留在傳回值中。

limit

每個 subject 字串中,每個模式的最大可能取代次數。預設為 -1 (無限制)。

count

如果指定,則此變數將會填入已完成的取代次數。

傳回值

如果 subject 參數是陣列,則 preg_replace() 會傳回陣列,否則會傳回字串。

如果找到符合的項目,則會傳回新的 subject,否則會傳回未變更的 subject,如果發生錯誤,則會傳回 null

錯誤/例外

使用 "\e" 修飾符是錯誤的;在這種情況下,會發出 E_WARNING

如果傳遞的正規表示式模式無法編譯為有效的正規表示式,則會發出 E_WARNING

範例

範例 #1 使用後面接著數字字面值的反向參考

<?php
$string
= 'April 15, 2003';
$pattern = '/(\w+) (\d+), (\d+)/i';
$replacement = '${1}1,$3';
echo
preg_replace($pattern, $replacement, $string);
?>

上面的範例將輸出

April1,2003

範例 #2 使用索引陣列與 preg_replace()

<?php
$string
= 'The quick brown fox jumps over the lazy dog.';
$patterns = array();
$patterns[0] = '/quick/';
$patterns[1] = '/brown/';
$patterns[2] = '/fox/';
$replacements = array();
$replacements[2] = 'bear';
$replacements[1] = 'black';
$replacements[0] = 'slow';
echo
preg_replace($patterns, $replacements, $string);
?>

上面的範例將輸出

The bear black slow jumps over the lazy dog.

透過 ksort 排序模式和取代項目,我們應該就能得到想要的結果。

<?php
ksort
($patterns);
ksort($replacements);
echo
preg_replace($patterns, $replacements, $string);
?>

上面的範例將輸出

The slow black bear jumps over the lazy dog.

範例 #3 取代多個值

<?php
$patterns
= array ('/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/',
'/^\s*{(\w+)}\s*=/');
$replace = array ('\3/\4/\1\2', '$\1 =');
echo
preg_replace($patterns, $replace, '{startDate} = 1999-5-27');
?>

上面的範例將輸出

$startDate = 5/27/1999

範例 #4 移除空白

此範例會從字串中移除多餘的空白。

<?php
$str
= 'foo o';
$str = preg_replace('/\s\s+/', ' ', $str);
// 現在會是 'foo o'
echo $str;
?>

範例 #5 使用 count 參數

<?php
$count
= 0;

echo
preg_replace(array('/\d/', '/\s/'), '*', 'xp 4 to', -1 , $count);
echo
$count; //3
?>

上面的範例將輸出

xp***to
3

注意事項

注意:

當使用陣列搭配 patternreplacement 時,鍵會依照它們在陣列中出現的順序處理。這**不一定**與數字索引順序相同。如果您使用索引來識別哪個 pattern 應該被哪個 replacement 取代,您應該在呼叫 preg_replace() 之前,先對每個陣列執行 ksort()

注意:

patternreplacement 都是陣列時,比對規則會依序運作。也就是說,第二個 pattern/replacement 配對會作用在第一個 pattern/replacement 配對的結果字串上,而不是原始字串。如果您想模擬並行運作的取代,例如交換兩個值,請先將一個模式取代為一個中間預留位置,然後在後面的配對中,將該中間預留位置取代為所需的取代值。

<?php
$p
= array('/a/', '/b/', '/c/');
$r = array('b', 'c', 'd');
print_r(preg_replace($p, $r, 'a'));
// 印出 d
?>

參見

新增註解

使用者貢獻註解 10 則註解

arkani at iol dot pt
15 年前
因為我搜尋這個很久了

如果您嘗試比對該字元,以下字元應被跳脫

\ ^ . $ | ( ) [ ]
* + ? { } ,

特殊字元定義
\ 跳脫下一個元字元
^ 比對行首
. 比對任何字元(除了換行符號)
$ 比對行尾(或在行尾換行符號之前)
| 選擇
() 分組
[] 字元類別
* 比對 0 或多次
+ 比對 1 或多次
? 比對 1 或 0 次
{n} 精確比對 n 次
{n,} 比對至少 n 次
{n,m} 比對至少 n 次但不超過 m 次
更多特殊字元的東西
\t tab (HT, TAB)
\n 換行符號 (LF, NL)
\r 返回 (CR)
\f 換頁 (FF)
\a 警報(蜂鳴)(BEL)
\e 跳脫(類似 troff)(ESC)
\033 八進位字元(類似 PDP-11)
\x1B 十六進位字元
\c[ 控制字元
\l 下一個字元小寫(類似 vi)
\u 下一個字元大寫(類似 vi)
\L 小寫直到 \E(類似 vi)
\U 大寫直到 \E(類似 vi)
\E 結束大小寫修改(類似 vi)
\Q 引用(停用)模式元字元直到 \E
甚至更多特殊字元
\w 比對「單字」字元(字母數字加上「_」)
\W 比對非單字字元
\s 比對空白字元
\S 比對非空白字元
\d 比對數字字元
\D 比對非數字字元
\b 比對單字邊界
\B 比對非單字邊界
\A 僅在字串開頭比對
\Z 僅在字串結尾比對,或在結尾的換行符號之前比對
\z 僅在字串結尾比對
\G 僅在先前 m//g 停止的位置比對(僅適用於 /g)
Anonymous
8 個月前
您只能在取代字串中使用數字反向參照,但不能使用具名反向參照
<?php
echo preg_replace('#(\d+)#', '\1 $1 ${1}', '123');
// 123 123 123
echo preg_replace('#(?<digits>\d+)#', '\digits $digits ${digits}', '123');
// \digits $digits ${digits}
?>

若要使用具名反向參照,您必須使用 preg_replace_callback
<?php
echo preg_replace_callback('#(?<digits>\d+)#', function( $m ){
return
"$m[1] $m[digits] {$m['digits']}";
},
'123');
// 123 123 123

echo preg_replace_callback('#(?<digits>\d+)#', fn($m) => "$m[1] $m[digits] {$m['digits']}", '123');
// 123 123 123
?>

參見 https://bugs.php.net/bug.php?id=81469
nik at rolls dot cc
11 年前
若要將 Pascal/CamelCase 分割為首字母大寫格式(例如,轉換描述性的類別名稱以用於人類可讀的前端),您可以使用以下函式

<?php
function expandCamelCase($source) {
return
preg_replace('/(?<!^)([A-Z][a-z]|(?<=[a-z])[^a-z]|(?<=[A-Z])[0-9_])/', ' $1', $source);
}
?>

之前
ExpandCamelCaseAPIDescriptorPHP5_3_4Version3_21Beta
之後
Expand Camel Case API Descriptor PHP 5_3_4 Version 3_21 Beta
ismith at nojunk dot motorola dot com
17 年前
請注意,當使用 "/u" 修飾符時,如果您的輸入文字包含任何錯誤的 UTF-8 碼序列,則 preg_replace 將會傳回一個空字串,無論是否有任何比對。

這是因為如果字串包含錯誤的 UTF-8,PCRE 函式庫會傳回錯誤碼。
sternkinder at gmail dot com
17 年前
從我所看到的,問題在於,如果您直接將所有 'A' 取代為 'T',您無法確定之後哪些 'T' 應該被取代為 'A'。這可以透過簡單地將所有 'A' 替換為另一個字元(例如 '_' 或您喜歡的任何字元)來解決,然後將所有 'T' 替換為 'A',然後將所有 '_'(或您選擇的任何字元)替換為 'A'。

<?php
$dna
= "AGTCTGCCCTAG";
echo
str_replace(array("A","G","C","T","_","-"), array("_","-","G","A","T","C"), $dna); // 輸出結果將會是 TCAGACGGGATC
?>

雖然我不知道 Perl 中的音譯是如何運作的(但我記得它有點類似於 UNIX 的 "tr" 命令),我會建議使用以下函式來「切換」單一字元。

<?php
function switch_chars($subject,$switch_table,$unused_char="_") {
foreach (
$switch_table as $_1 => $_2 ) {
$subject = str_replace($_1,$unused_char,$subject);
$subject = str_replace($_2,$_1,$subject);
$subject = str_replace($unused_char,$_2,$subject);
}
return
$subject;
}

echo
switch_chars("AGTCTGCCCTAG", array("A"=>"T","G"=>"C")); // 輸出結果將會是 TCAGACGGGATC
?>
php-comments-REMOVE dot ME at dotancohen dot com
16 年前
以下是一個將希伯來文的結尾字符轉換為
它們在單字中間出現時的正常等效字符的函式。
/b 參數不會將希伯來文字母視為單字的一部分,
因此我必須繞過這個限制。

<?php

$text
="עברית מבולגנת";

function
hebrewNotWordEndSwitch ($from, $to, $text) {
$text=
preg_replace('/'.$from.'([א-ת])/u','$2'.$to.'$1',$text);
return
$text;
}

do {
$text_before=$text;
$text=hebrewNotWordEndSwitch("ך","כ",$text);
$text=hebrewNotWordEndSwitch("ם","מ",$text);
$text=hebrewNotWordEndSwitch("ן","נ",$text);
$text=hebrewNotWordEndSwitch("ף","פ",$text);
$text=hebrewNotWordEndSwitch("ץ","צ",$text);
} while (
$text_before!=$text );

print
$text; // עברית מסודרת!

?>

do-while 迴圈對於字母的多個實例是必要的,例如
「אנני」將會從「אןןי」開始。請注意,仍然存在
帶有 gershiim 的縮寫的問題,但這不是一個難以解決的問題。
該程式碼正在 http://gibberish.co.il 上使用,您可以
使用它來翻譯錯誤編碼的希伯來語、音譯,以及一些
其他與希伯來語相關的功能。

為了確保單字結尾不會有常規字元,只需
將所有常規字元轉換為其最終形式,然後
執行此函式。盡情享用!
me at perochak dot com
13 年前
如果您想要移除一個標籤以及它內部的文字,請使用以下程式碼。

<?php
preg_replace
('/(<tag>.+?)+(<\/tag>)/i', '', $string);
?>

範例
<?php $string='<span class="normalprice">55 PKR</span>'; ?>

<?php
$string
= preg_replace('/(<span class="normalprice">.+?)+(<\/span>)/i', '', $string);
?>

這將會產生一個 null 或空字串。

<?php
$string
='My String <span class="normalprice">55 PKR</span>';

$string = preg_replace('/(<span class="normalprice">.+?)+(<\/span>)/i', '', $string);
?>

這將會產生一個「 My String」
bublifuk at mailinator dot com
6 年前
分隔符號可以是任何 ASCII 非字母數字、非反斜線、非空白字元: !"#$%&'*+,./:;=?@^_`|~- 和 ({[<>]})
razvan_bc at yahoo dot com
2 年前
如何在不移除 crln = \r\n 或 cr \r 每一行的情況下,替換程式碼內的所有註解?

<?php
$txt_target
=<<<t1
this;// dsdsds
nope

/*
ok
*/
is;huge
/*text bla*/
/*bla*/

t1;

/*
=======================================================================
預期結果:
=======================================================================
this;
nope

is;huge
=======================================================================
在十六進位檢視器中視覺化 .. to_check_with_a_hex_viewer.txt ...
t h i s ; LF TAB n o p e CR LF CR LF i s ; h u g e CR LF
74 68 69 73 3b 0a 09 6e 6f 70 65 0d 0a 0d 0a 69 73 3b 68 75 67 65 0d 0a
我在神話般的 TOTAL COMMANDER 中使用了 F3(檢視器 + 選項 3:十六進位)!
=======================================================================
*/

echo '<hr><pre>';
echo
$txt_target;
echo
'</pre>';

// 單行 '//' 註解
$txt_target = preg_replace('![ \t]*//.*[ \t]*!', '', $txt_target);

// /* 註解 */
$txt_target = preg_replace('/\/\*([^\/]*)\*\/(\s+)/smi', '', $txt_target);
echo
'<hr><pre>';
echo
$txt_target;
echo
'</pre><hr>';

file_put_contents('to_check_with_a_hex_viewer.txt',$txt_target);

?>
mail at johanvandemerwe dot nl
5 年前
用於替換括號中的簡碼的範例

所使用的簡碼純粹用於教育目的,因為它們可以更短,例如「italic」到「i」或「bold」到「b」。

範例文字
----
此範例示範如何使用 [italic]斜體[/italic]、[bold]粗體[/bold]、[underline]底線[/underline] 和 [strikethrough]刪除線[/striketrhough] 文字。

使用此函式

<?php
function textDecoration($html)
{
$patterns = [
'/\[(italic)\].*?\[\/\1\] ?/',
'/\[(bold)\].*?\[\/\1\] ?/',
'/\[(underline)\].*?\[\/\1\] ?/'
];

$replacements = [
'<i>$1</i>',
'<strong>$1</strong>',
'<u>$1</u>'
];

return
preg_replace($patterns, $replacements, $html);
}

$html = textDecoration($html);

echo
$html; // 或傳回
?>

結果為
----
此範例示範如何使用 <i>斜體</i>、<b>粗體</b> 和 <u>底線</u> 以及 [strikethrough]刪除線[/striketrhough] 文字。

注意!
在 patterns 和 replacements 陣列中,沒有 [strikethrough]刪除線[/striketrhough] 的後備方案
To Top