PHPのお勉強!

PHP TOP

preg_replace

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

preg_replace正規表現検索および置換を行う

説明

preg_replace(
    string|array $pattern,
    string|array $replacement,
    string|array $subject,
    int $limit = -1,
    int &$count = null
): string|array|null

subject に関して pattern を用いて検索を行い、 replacement に置換します。

パターンではなく、文字列と正確にマッチさせたい場合、 この関数の代わりに str_replace()str_ireplace() を使うことを検討してください。

パラメータ

pattern

検索を行うパターン。文字列もしくは配列とすることができます。

PCRE 修飾子 も使えます。

replacement

置換を行う文字列もしくは文字列の配列。 この引数が文字列で、pattern 引数が配列の場合、 すべてのパターンがこの文字列に置換されます。 pattern および replacement のいずれもが配列の場合、各 pattern は 対応する replacement に置換されます。 もし、replacement 配列の要素の数が pattern 配列よりも少ない場合は、余った pattern は 空文字に置換されます。

replacement では、 \n 形式または $n 形式で参照を指定することができます。 後者の形式の方が好ましい形式です。各参照は、n 番目のキャプチャ用サブパターンにマッチしたテキストにより置換されます。 n は 0 から 99 までとすることができ、 \0 または $0 は パターン全体にマッチするテキストを参照します。キャプチャ用サブパターンの番号 については、その左括弧が左から右に(1から)カウントされます。 string に含まれるバックスラッシュリテラルは、エスケープが必須であることに注意して下さい。

後方参照の直後に他の数字が続くような置換 (replacement) パターンを 使用する場合(すなわち、マッチしたパターンの直後に数字リテラルを置く 場合)、後方参照を行うために通常の \1 表記を 使用することができません。例えば、\11 は、 後方参照 \1 の後にリテラル 1 が続くのか、後方参照 \11 で その後には何も続かないのかが不明のため、 preg_replace() を混乱させる可能性があります。 この場合、解決策は、${1}1 を使用することです。 こうすることで、1 はリテラルとなり、後方参照 $1 を明確に作成できます。

非推奨の e 修飾子を使用する際に、 この関数は後方参照を置換する文字列のうちの特定の文字 (具体的には '"\ および NULL) をエスケープします。 これは、後方参照をシングルクォートやダブルクォートを共用した場合 (たとえば 'strlen(\'$1\')+strlen("$2")') に構文エラーが発生しないようにするためのものです。 PHP の 文字列構文 を意識し、 文字列がどのように解釈されるのかを正確に知っておくようにしましょう。

subject

検索・置換対象となる文字列もしくは文字列の配列

subject が配列の場合、検索と置換は subject の各要素に対して行われ、戻り値も配列となります。

subject が連想配列の場合、 キーは戻り値でも保持されます。

limit

subject 文字列において、各パターンによる 置換を行う最大回数。デフォルトは -1 (制限無し)。

count

この引数が指定されると、置換回数が渡されます。

戻り値

preg_replace() は、 subject 引数が配列の場合は配列を、 その他の場合は文字列を返します。

パターンがマッチした場合、〔置換が行われた〕新しい 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 添字配列の使用

<?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.

pattern と replacement を 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);
// This will be 'foo o' now
echo $str;
?>

例5 count 引数の使用

<?php
$count
= 0;

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

上の例の出力は以下となります。

xp***to
3

注意

注意:

pattern および replacement を使用する際、配列の並び順に処理されます。添字は整数であっても、 その並びは値の小さい順になっているとは限りません。 ですから、配列の添字を使って、どの 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'));
// prints d
?>

参考

add a note

User Contributed Notes 10 notes

up
781
arkani at iol dot pt
15 years ago
Because i search a lot 4 this:

The following should be escaped if you are trying to match that character

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

Special Character Definitions
\ Quote the next metacharacter
^ Match the beginning of the line
. Match any character (except newline)
$ Match the end of the line (or before newline at the end)
| Alternation
() Grouping
[] Character class
* Match 0 or more times
+ Match 1 or more times
? Match 1 or 0 times
{n} Match exactly n times
{n,} Match at least n times
{n,m} Match at least n but not more than m times
More Special Character Stuff
\t tab (HT, TAB)
\n newline (LF, NL)
\r return (CR)
\f form feed (FF)
\a alarm (bell) (BEL)
\e escape (think troff) (ESC)
\033 octal char (think of a PDP-11)
\x1B hex char
\c[ control char
\l lowercase next char (think vi)
\u uppercase next char (think vi)
\L lowercase till \E (think vi)
\U uppercase till \E (think vi)
\E end case modification (think vi)
\Q quote (disable) pattern metacharacters till \E
Even More Special Characters
\w Match a "word" character (alphanumeric plus "_")
\W Match a non-word character
\s Match a whitespace character
\S Match a non-whitespace character
\d Match a digit character
\D Match a non-digit character
\b Match a word boundary
\B Match a non-(word boundary)
\A Match only at beginning of string
\Z Match only at end of string, or before newline at the end
\z Match only at end of string
\G Match only where previous m//g left off (works only with /g)
up
3
Anonymous
9 months ago
You can only use numeric backreferences in the replacement string, but not named ones:
<?php
echo preg_replace('#(\d+)#', '\1 $1 ${1}', '123');
// 123 123 123
echo preg_replace('#(?<digits>\d+)#', '\digits $digits ${digits}', '123');
// \digits $digits ${digits}
?>

To use named backreferences, you have to use 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
?>

See https://bugs.php.net/bug.php?id=81469
up
4
nik at rolls dot cc
11 years ago
To split Pascal/CamelCase into Title Case (for example, converting descriptive class names for use in human-readable frontends), you can use the below function:

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

Before:
ExpandCamelCaseAPIDescriptorPHP5_3_4Version3_21Beta
After:
Expand Camel Case API Descriptor PHP 5_3_4 Version 3_21 Beta
up
2
ismith at nojunk dot motorola dot com
17 years ago
Be aware that when using the "/u" modifier, if your input text contains any bad UTF-8 code sequences, then preg_replace will return an empty string, regardless of whether there were any matches.

This is due to the PCRE library returning an error code if the string contains bad UTF-8.
up
2
sternkinder at gmail dot com
17 years ago
From what I can see, the problem is, that if you go straight and substitute all 'A's wit 'T's you can't tell for sure which 'T's to substitute with 'A's afterwards. This can be for instance solved by simply replacing all 'A's by another character (for instance '_' or whatever you like), then replacing all 'T's by 'A's, and then replacing all '_'s (or whatever character you chose) by 'A's:

<?php
$dna
= "AGTCTGCCCTAG";
echo
str_replace(array("A","G","C","T","_","-"), array("_","-","G","A","T","C"), $dna); //output will be TCAGACGGGATC
?>

Although I don't know how transliteration in perl works (though I remember that is kind of similar to the UNIX command "tr") I would suggest following function for "switching" single chars:

<?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")); //output will be TCAGACGGGATC
?>
up
2
php-comments-REMOVE dot ME at dotancohen dot com
16 years ago
Below is a function for converting Hebrew final characters to their
normal equivelants should they appear in the middle of a word.
The /b argument does not treat Hebrew letters as part of a word,
so I had to work around that limitation.

<?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; // עברית מסודרת!

?>

The do-while is necessary for multiple instances of letters, such
as "אנני" which would start off as "אןןי". Note that there's still the
problem of acronyms with gershiim but that's not a difficult one
to solve. The code is in use at http://gibberish.co.il which you can
use to translate wrongly-encoded Hebrew, transliterize, and some
other Hebrew-related functions.

To ensure that there will be no regular characters at the end of a
word, just convert all regular characters to their final forms, then
run this function. Enjoy!
up
-1
me at perochak dot com
13 years ago
If you would like to remove a tag along with the text inside it then use the following code.

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

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

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

This will results a null or empty string.

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

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

This will results a " My String"
up