Using this for SEO urls. I had to modify it a bit to get through the word wrap. Pretty sure you can one line it a lot of it.
<?php
public static function encodeUrlParam ( $string )
{
$string = trim($string);
if ( ctype_digit($string) )
{
return $string;
}
else
{
// replace accented chars
$accents = '/&([A-Za-z]{1,2})(grave|acute|circ|cedil|uml|lig);/';
$string_encoded = htmlentities($string,ENT_NOQUOTES,'UTF-8');
$string = preg_replace($accents,'$1',$string_encoded);
// clean out the rest
$replace = array('([\40])','([^a-zA-Z0-9-])','(-{2,})');
$with = array('-','','-');
$string = preg_replace($replace,$with,$string);
}
return strtolower($string);
}
?>
preg_replace
(PHP 4, PHP 5)
preg_replace — 正規表現検索および置換を行う
説明
subject に関して pattern を用いて検索を行い、 replacement に置換します。
パラメータ
- pattern
-
検索を行うパターン。文字列もしくは配列とすることができます。
e 修飾子を設定すると、preg_replace() は、参照先の対応する置換を行う際に replacement 引数を PHP コードであるとして取り扱います。 replacement には有効な PHP コードを記述してください。 さもないと、preg_replace() がある行でパースエラーが 発生してしまいます。
- replacement
-
置換を行う文字列もしくは文字列の配列。 この引数が文字列で、pattern 引数が配列の場合、 すべてのパターンがこの文字列に置換されます。 pattern および replacement のいずれもが配列の場合、各 pattern は 対応する replacement に置換されます。 もし、replacement 配列の要素の数が pattern 配列よりも少ない場合は、余った pattern は 空文字に置換されます。
replacement では、 \\n 形式または $$n 形式(PHP 4.0.4 以降)で参照を指定することができます。 後者の形式の方が好ましい形式です。各参照は、n 番目のキャプチャ用サブパターンにマッチしたテキストにより置換されます。 n は 0 から 99 までとすることができ、 \\0 または $0 は パターン全体にマッチするテキストを参照します。キャプチャ用サブパターンの番号 については、その左括弧が左から右に(1から)カウントされます。 置換文字でバックスラッシュを使用する場合は、二重化する必要があります (PHP の文字列 "\\\\" となります)。
後方参照の直後に他の数字が続くような置換 (replacement) パターンを 使用する場合(すなわち、マッチしたパターンの直後に数字リテラルを置く 場合)、後方参照を行うために通常の \\1 表記を 使用することができません。例えば、\\11 は、 後方参照 \\1 の後にリテラル 1 が続くのか、後方参照 \\11 で その後には何も続かないのかが不明のため、 preg_replace() を混乱させる可能性があります。 この場合、解決策は、\${1}1 を使用することです。 こうすることで、1 はリテラルとなり、後方参照 $1 を明確に作成できます。
e 修飾子を使用する際に、 この関数は後方参照を置換する文字列のうちの特定の文字 (具体的には '、"、 \ および NULL) をエスケープします。 これは、後方参照をシングルクォートやダブルクォートを共用した場合 (たとえば 'strlen(\'$1\')+strlen("$2")') に構文エラーが発生しないようにするためのものです。 PHP の 文字列構文 を意識し、 文字列がどのように解釈されるのかを正確に知っておくようにしましょう。
- subject
-
検索・置換対象となる文字列もしくは文字列の配列
subject が配列の場合、検索と置換は subject の各要素に対して行われ、返り値も配列となります。
- limit
-
subject 文字列において、各パターンによる 置換を行う最大回数。デフォルトは -1 (制限無し)。
- count
-
この引数が指定されると、置換回数が渡されます。
返り値
preg_replace() は、 subject 引数が配列の場合は配列を、 その他の場合は文字列を返します。
パターンがマッチした場合、〔置換が行われた〕新しい subject を返します。マッチしなかった場合、subject をそのまま返します。エラーが発生した場合、NULL を返します。
変更履歴
| バージョン | 説明 |
|---|---|
| 5.1.0 | count 引数が追加されました。 |
| 4.0.4 | replacement 引数に '$n' 形式が使用できるようになりました。 |
| 4.0.2 | limit 引数が追加されました。 |
例
例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 jumped over the lazy dog.';
$patterns[0] = '/quick/';
$patterns[1] = '/brown/';
$patterns[2] = '/fox/';
$replacements[2] = 'bear';
$replacements[1] = 'black';
$replacements[0] = 'slow';
echo preg_replace($patterns, $replacements, $string);
?>
上の例の出力は以下となります。
The bear black slow jumped over the lazy dog.
pattern と replacement を ksort すると、所望のものが得られます。
<?php
ksort($patterns);
ksort($replacements);
echo preg_replace($patterns, $replacements, $string);
?>
上の例の出力は以下となります。
The slow black bear jumped 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 'e' 修飾子の使用
<?php
preg_replace("/(<\/?)(\w+)([^>]*>)/e",
"'\\1'.strtoupper('\\2').'\\3'",
$html_body);
?>
入力テキストのすべての HTML タグを大文字に変換します。
例5 空白の削除
この例は、文字列から余分な空白を取り除きます。
<?php
$str = 'foo o';
$str = preg_replace('/\s\s+/', ' ', $str);
// This will be 'foo o' now
echo $str;
?>
例6 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() を実行しておくべきです。
参考
- preg_filter() - Perform a regular expression search and replace
- preg_match() - 正規表現によるマッチングを行う
- preg_replace_callback() - 正規表現検索を行い、コールバック関数を使用して置換を行う
- preg_split() - 正規表現で文字列を分割する
preg_replace
24-Apr-2009 02:15
16-Apr-2009 06:56
To make seo url from title or any text:
<?php
function CleanFileName( $Raw ){
$Raw = trim($Raw);
$RemoveChars = array( "([\40])" , "([^a-zA-Z0-9-])", "(-{2,})" );
$ReplaceWith = array("-", "", "-");
return preg_replace($RemoveChars, $ReplaceWith, $Raw);
}
echo CleanFileName('whatever $4 sd- -sdf- @ sd 8 as +% sdf ;');
?>
08-Apr-2009 12:09
The issue described by arie below is not actually a bug, but expected behaviour. The PCRE Regular Expression Details says: "The definition of letters and digits is controlled by PCRE's character tables, and may vary if locale-specific matching is taking place. For example, in the "fr" (French) locale, some character codes greater than 128 are used for accented letters, and these are matched by \w."
09-Mar-2009 08:50
<?php
//Be carefull with utf-8, even with unicode and utf-8 support enabled, a pretty odd bug occurs depending on your operating system
$str = "Hi, my name is Arié!<br />";
echo preg_replace('#\bArié\b#u', 'Gontran', $str);
//on windows system, output is "Hi, my name is Gontran<br />"
//on unix system, output is "Hi, my name is Arié<br />"
echo preg_replace('#\bArié(|\b)#u', 'Gontran', $str);
//on windows and unix system, output is "Hi, my name is Gontran<br />"
04-Mar-2009 07:00
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)
18-Feb-2009 12:02
<?php
$converted =
array(
//3 of special chars
'/(;)/ie',
'/(#)/ie',
'/(&)/ie',
//MySQL reserved words!
//Check mysql website!
'/(ACTION)/ie', '/(ADD)/ie', '/(ALL)/ie', '/(ALTER)/ie', '/(ANALYZE)/ie', '/(AND)/ie', '/(AS)/ie', '/(ASC)/ie',
//remaining of special chars
'/(<)/ie', '/(>)/ie', '/(\.)/ie', '/(,)/ie', '/(\?)/ie', '/(`)/ie', '/(!)/ie', '/(@)/ie', '/(\$)/ie', '/(%)/ie', '/(\^)/ie', '/(\*)/ie', '/(\()/ie', '/(\))/ie', '/(_)/ie', '/(-)/ie', '/(\+)/ie',
'/(=)/ie', '/(\/)/ie', '/(\|)/ie', '/(\\\)/ie', "/(')/ie", '/(")/ie', '/(:)/'
);
$input_text = preg_replace($converted, "UTF_to_Unicode('\\1')", $text);
function UTF_to_Unicode($data){
//return $data;
}
?>
The above example useful for filtering input data, then saving into mysql database, it's not need tobe decoded again, just use UTF-8 as charset.
Please Note escaping special chars between delimiter..
10-Feb-2009 01:41
I have written a short introduction and a colorful cheat sheet for Perl Compatible Regular Expressions (PCRE):
http://www.bitcetera.com/en/techblog/2008/04/01/regex-in-a-nutshell/
04-Jan-2009 08:08
I was needing regular expression with brace matching, but i was not able to find anything for this problem.
So, if i had :
\bold{something \underline{another thing} and another bold thing}
My regexp would stop at the first closing brace, and it seemed to be a common problem with regular expression, often discussed on forums.
So here is the snippet i used, perhaps it'll be useful :
<?php
function preg_replace_with_braces($Regexp,$Remplacement,$Texte)
{
preg_match_all($Regexp,$Texte,$Resultats,PREG_SET_ORDER);
$SVGRemplacement=$Remplacement;
foreach($Resultats as $Resultat)
{//For each result
$Remplacement=$SVGRemplacement;
foreach($Resultat as $n=>$Match)
{//For each set of capturing parenthesis
if($n>0 && strpos($Match,'{')!==false)
{//We find a open brace in our regexp : we'll need to find the closing one !
$InitialMatch=$Match;
$Offset=strpos($Texte,$Resultat[0]);
$Offset=strpos($Texte,$Match,$Offset);//We move the caret to the good place : let's start !
$Depart=$Offset;
$Taille=strlen($Texte);
$NestingLevel=0;
while($NestingLevel>=0 && $Offset<$Taille)
{//Browse the string, searching for braces. Perhaps the most important place !
$Offset++;
if($Texte[$Offset]=='{')
$NestingLevel++;
elseif($Texte[$Offset]=='}')
$NestingLevel--;
}
$Match=substr($Texte,$Depart,$Offset-$Depart);
$Resultat[0]=str_replace($InitialMatch,$Match,$Resultat[0]);
}
$Remplacement=str_replace('$' . $n,$Match,$Remplacement);
}
$Texte=str_replace($Resultat[0],$Remplacement,$Texte);
}
return $Texte;
}
?>
Hope it'll be useful !
I know it's pretty odd and unclean, but that was a quick workaround i had.
01-Jan-2009 12:31
For BBcode, rather than having two different arrays you can use the same one.
<?php
$bbcode = array(
"/\[b\](.*?)\[\/b\]/is" => "<strong>$1</strong>",
"/\[u\](.*?)\[\/u\]/is" => "<u>$1</u>",
"/\[url\=(.*?)\](.*?)\[\/b\]/is" => "<a href='$1'>$2</a>"
);
$text = "[b]Text[/b][u]Text[/u]";
$text = preg_replace(array_keys($bbcode), array_values($bbcode), $text);
?>
23-Dec-2008 08:47
<?php
/*
Coding across linux, mac, and windows gets annoying dealing with errors resulting from EOL format in config files, etc.
Standardize to CRLF format.
Instead of using one regex I just broke this up into smaller groups -
may take longer to execute three statements rather than one,
but it also granularizes the use case.
*/
//different formats all living together
$s = "Testing 1.\r" . "Testing 2.\n" . "Testing 3.\r\n" . "Testing 4.\n\r:END";
$s = preg_replace("/(?<!\\n)\\r+(?!\\n)/", " :REPLACED: \r\n", $s); //replace just CR with CRLF
$s = preg_replace("/(?<!\\r)\\n+(?!\\r)/", " :REPLACED: \r\n", $s); //replace just LF with CRLF
$s = preg_replace("/(?<!\\r)\\n\\r+(?!\\n)/", " :REPLACED: \r\n", $s); //replace misordered LFCR with CRLF
echo $s;
/*
output:
Testing 1. :REPLACED:
Testing 2. :REPLACED:
Testing 3.
Testing 4. :REPLACED:
:END
*/
?>
28-Nov-2008 06:13
An alternative to the method suggested by sheri is to remember that the regex modifier '$' only looks at the end of the STRING, the example given is a single string consisting of multiple lines.
Try:
<?php
// Following is 1 string containing 3 lines
$s = "Testing, testing.\r\n"
. "Another testing line.\r\n"
. "Testing almost done.";
echo preg_replace('/\.\\r\\n/m', '@\r\n', $s);
?>
This results in the string:
Testing, testing@\r\nAnother testing line@\r\nTesting almost done.
19-Nov-2008 12:47
I use this to prevent users from overdoing repeated text. The following function only allows 3 identical characters at a time and also takes care of repetitions with whitespace added.
This means that 'haaaaaaleluuuujaaaaa' becomes 'haaaleluuujaaa' and 'I am c o o o o o o l' becomes 'I am c o o o l'
<?php
//Example of user input
$str = "aaaaaaaaaaabbccccccccaaaaad d d d d d d ddde''''''''''''";
function stripRepeat($str) {
//Do not allow repeated whitespace
$str = preg_replace("/(\s){2,}/",'$1',$str);
//Result: aaaaaaaaaaabbccccccccaaaaad d d d d d d ddde''''''''''''
//Do not allow more than 3 identical characters separated by any whitespace
$str = preg_replace('{( ?.)\1{4,}}','$1$1$1',$str);
//Final result: aaabbcccaaad d d ddde'''
return $str;
}
?>
To prevent any repetitions of characters, you only need this:
<?php
$str = preg_replace('{(.)\1+}','$1',$str);
//Result: abcad d d d d d d de'
?>
17-Nov-2008 05:25
String to filename:
<?php
function string_to_filename($word) {
$tmp = preg_replace('/^\W+|\W+$/', '', $word); // remove all non-alphanumeric chars at begin & end of string
$tmp = preg_replace('/\s+/', '_', $tmp); // compress internal whitespace and replace with _
return strtolower(preg_replace('/\W-/', '', $tmp)); // remove all non-alphanumeric chars except _ and -
}
?>
Returns a usable & readable filename.
16-Oct-2008 01:48
You can do seo permalink to your subject with this function as wordpress.
<?php
function seo_permalink($value) {
$turkce=array(
"ş","Ş","ı","(",
")","'","ü","Ü",
"ö","Ö","ç","Ç",
" ","/","*","?",
"ş","Ş","ı","ğ",
"Ğ","İ","ö","Ö",
"Ç","ç","ü","Ü");
$duzgun=array(
"s","S","i","",
"","","u","U",
"o","O","c","C",
"","-","-","",
"s","S","i","g",
"G","I","o","O",
"C","c","u","U");
$value=str_replace($turkce,$duzgun,$value);
$value = preg_replace("@[^A-Za-z0-9\-_]+@i","",$value);
return $value;
}
echo "http://www.pyromus.com/";
echo seo("convert turkish sentence to seo url value");
?>
22-Sep-2008 09:32
The situation described below by dyer85 at gmail on 28-Aug-2008 at 08:41 can be addressed (since PCRE version 7.3) by including "(*ANYCRLF)" at the start of the pattern. Then linebreaks will be detected for line endings typical of unix, mac and PC texts.
When included in the pattern for the example cited, all expected replacements are made.
<?php
$s = "Testing, testing.\r\n"
. "Another testing line.\r\n"
. "Testing almost done.";
echo preg_replace('/(*ANYCRLF)\.$/m', '.@', $s);
?>
14-Sep-2008 08:46
after long time of tring get rid of \n\r and <BR> stuff i've came with this...
(i done some changes in clicklein() function...)
<?php
function clickable($url){
$url = str_replace("\\r","\r",$url);
$url = str_replace("\\n","\n<BR>",$url);
$url = str_replace("\\n\\r","\n\r",$url);
$in=array(
'`((?:https?|ftp)://\S+[[:alnum:]]/?)`si',
'`((?<!//)(www\.\S+[[:alnum:]]/?))`si'
);
$out=array(
'<a href="$1" rel=nofollow>$1</a> ',
'<a href="http://$1" rel=\'nofollow\'>$1</a>'
);
return preg_replace($in,$out,$url);
}
?>
07-Sep-2008 12:16
Hello I am the admin of http://www.webb3.net/ I got this function for templates.
<?php
$file = "filename.tpl";
$contents = file_get_contents($file);
$website_tpl = 'something';
$text = preg_replace('/\{(\w+)\}/e', '$$1_tpl', $TEMPLATE);
echo $text
?>
With this if you have a file filename.tpl and you have the text {website} it will replace it with something as you can see above!
-<a href="http://www.webb3.net">http://www.webb3.net/</a>
29-Aug-2008 02:41
There seems to be some unexpected behavior when using the /m modifier when the line terminators are win32 or mac format.
If you have a string like below, and try to replace dots, the regex won't replace correctly:
<?php
$s = "Testing, testing.\r\n"
. "Another testing line.\r\n"
. "Testing almost done.";
echo preg_replace('/\.$/m', '.@', $s); // only last . replaced
?>
The /m modifier doesn't seem to work properly when CRLFs or CRs are used. Make sure to convert line endings to LFs (*nix format) in your input string.
23-Aug-2008 08:42
preg_replace is greedy by default, and the behaviour of ? on the pattern is to make it non-greedy contrary to what i read on PCRE docs.
<?php
$str ="asdfd adsfd aaaadasd";
$str = preg_replace("/(a)(.*)(d)/","a($2)d",$str);
// a(sdfd adsfd aaaadas)d
$str = preg_replace("/(a)(.*)?(d)/U","a($2)d",$str);
// a(s)dfd a()dsfd a(aaa)da(s)d
?>
which is what i wanted.
31-Jul-2008 01:08
<?PHP
function strip_tags_attributes($sSource, $aAllowedTags = FALSE, $aDisabledAttributes = FALSE, $aAllowedProperties = 'font|font-size|font-weight|color' . '|text-align|text-decoration|margin|margin-left' . '|margin-top|margin-bottom|margin-right|padding' . '|padding-top|padding-left|padding-right|padding-bottom' . '|width|height'){
if( !is_array( $aDisabledAttributes ) ){
$aDisabledAttributes = array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavaible', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragdrop', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterupdate', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmoveout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
}
$sSource = stripcslashes( $sSource );
$sSource = strip_tags( $sSource, $aAllowedTags );
if( empty($aDisabledAttributes) ){
return $sSource;
}
$aDisabledAttributes = @ implode('|', $aDisabledAttributes);
$sSource = preg_replace('/<(.*?)>/ie', "'<' . preg_replace(array('/javascript:[^\"\']*/i', '/(" . $aDisabledAttributes . ")[ \\t\\n]*=[ \\t\\n]*[\"\'][^\"\']*[\"\']/i', '/\s+/'), array('', '', ' '), stripslashes('\\1')) . '>'", $sSource );
$sSource = preg_replace('/\s(' . $aDisabledAttributes . ').*?([\s\>])/', '\\2', $sSource);
$regexp = '@([^;"]+)?(?<!'. $aAllowedProperties .'):(?!\/\/(.+?)\/)((.*?)[^;"]+)(;)?@is';
$sSource = preg_replace($regexp, '', $sSource);
$sSource = preg_replace('@[a-z]*=""@is', '', $sSource);
return $sSource;
}
?>
Online resource help skype name : globya
good luck !
30-Jul-2008 04:21
People using functions like scandir with user input and protecting against "../" by using preg_replace make sure you run ir recursivly untill preg_match no-long finds it, because if you don't the following can happen.
If a user gives the path:
"./....//....//....//....//....//....//....//"
then your script detects every "../" and removes them leaving:
"./../../../../../../../"
Which is proberly going back enough times to show root.
I just found this vunrability in an old script of mine, which was written several years ago.
Always do:
<?php
while( preg_match( [expression], $input ) )
{
$input = preg_replace( [expression], "", $input );
}
?>
30-Jul-2008 12:34
I just was trying to make a negated replace with a string NOT being in another string.
The code that is actually working:
<?php
$result = preg_replace('#{(?!disable1|disable2)[a-z0-9]+}#is', '$1', $foo);
?>
This code matches on all strings that do NOT start with "disable1" or "disable2" and contain of a-z0-9. It took me several hours to figuere out this very easy example!
Hope anyone could use it
25-Jul-2008 10:56
<?php
//:::replace with anything that you can do with searched string:::
//Marcin Majchrzak
//pixaltic.com
$c = "2 4 8";
echo ($c); //display:2 4 8
$cp = "/(\d)\s(\d)\s(\d)/e"; //pattern
$cr = "'\\3*\\2+\\1='.(('\\3')*('\\2')+('\\1'))"; //replece
$c = preg_replace($cp, $cr, $c);
echo ($c); //display:8*4+2=34
?>
16-Jul-2008 10:23
When you use the '$1', '$2', etc. replacement values, they can be either in double or single quotes. There is no need to worry about the dollar sign being interpreted as a variable or not:
<?php
print preg_replace("/I want (\S+) one/", "$1 is the one I want", "I want that one") . "\n";
print preg_replace("/I want (\S+) one/", '$1 is the one I want', "I want that one") . "\n";
?>
Both lines will print "that is the one I want".
11-Jul-2008 11:59
Take care when you try to strip whitespaces out of an UTF-8 text. Using something like:
<?php
$text = preg_replace( "{\s+}", ' ', $text );
?>
brokes in my case the letter à which is hex c3a0. But a0 is a whitespace. So use
<?php
$text = preg_replace( "{[ \t]+}", ' ', $text );
?>
to strip all spaces and tabs, or better, use a multibyte function like mb_ereg_replace.
07-Jul-2008 10:22
preg_replace (and other preg-functions) return null instead of a string when encountering problems you probably did not think about!
-------------------------
It may not be obvious to everybody that the function returns NULL if an error of any kind occurres. An error I happen to stumple about quite often was the back-tracking-limit:
http://de.php.net/manual/de/pcre.configuration.php
#ini.pcre.backtrack-limit
When working with HTML-documents and their parsing it happens that you encounter documents that have a length of over 100.000 characters and that may lead to certain regular-expressions to fail due the back-tracking-limit of above.
A regular-expression that is ungreedy ("U", http://de.php.net/manual/de/reference.pcre.pattern.modifiers.php) often does the job, but still: sometimes you just need a greedy regular expression working on long strings ...
Since, an unhandled return-value of NULL usually creates a consecutive error in the application with unwanted and unforeseen consequences, I found the following solution to be quite helpful and at least save the application from crashing:
<?php
$string_after = preg_replace( '/some_regexp/', "replacement", $string_before );
// if some error occurred we go on working with the unchanged original string
if (PREG_NO_ERROR !== preg_last_error())
{
$string_after = $string_before;
// put email-sending or a log-message here
} //if
// free memory
unset( $string_before );
?>
You may or should also put a log-message or the sending of an email into the if-condition in order to get informed, once, one of your regular-expressions does not have the effect you desired it to have.
21-Jun-2008 06:09
A simple BB like thing..
<?php
function AddBB($var) {
$search = array(
'/\[b\](.*?)\[\/b\]/is',
'/\[i\](.*?)\[\/i\]/is',
'/\[u\](.*?)\[\/u\]/is',
'/\[img\](.*?)\[\/img\]/is',
'/\[url\](.*?)\[\/url\]/is',
'/\[url\=(.*?)\](.*?)\[\/url\]/is'
);
$replace = array(
'<strong>$1</strong>',
'<em>$1</em>',
'<u>$1</u>',
'<img src="$1" />',
'<a href="$1">$1</a>',
'<a href="$1">$2</a>'
);
$var = preg_replace ($search, $replace, $var);
return $var;
}
?>
16-Apr-2008 10:35
For filename tidying I prefer to only ALLOW certain characters rather than converting particular ones that we want to exclude. To this end I use ...
<?php
$allowed = "/[^a-z0-9\\040\\.\\-\\_\\\\]/i";
preg_replace($allowed,"",$str));
?>
Allows letters a-z, digits, space (\\040), hyphen (\\-), underscore (\\_) and backslash (\\\\), everything else is removed from the string.
25-Mar-2008 02:45
This is in response to iasmin at amazingdiscoveries dot org's URL text to link function. Hope this is helpful to someone.
I played with it a bit and came up with this version (there were one or two little errors in the regex I think, also -- it didn't allow various necessary characters).
I start with a URL in brackets (this works for my case):
[http://www.site.com/path/that/may/be_long.php?fun=1]
It returns a link of the URL after the "http://":
www.site.com/path/that/may/b...
-----------
// Cuts off long URLs at $url_length, and appends "..."
function reduceurl($url, $url_length) {
$reduced_url = substr($url, 0, $url_length);
if (strlen($url) > $url_length) $reduced_url .= '...';
return $reduced_url;
}
// Makes URLs with brackets into links
// The regex searches for "http://" or equivalent, then various character possibilities (I don't know if it might be possible to exploit this if more characters were allowed). The "e" after the regex allows the reduceurl() to be evaluated.
function url2link($linktext) {
$linktext = preg_replace("#\[(([a-zA-Z]+://)([a-zA-Z0-9?&%.;:/=+_-]*))\]#e", "'<a href=\"$1\" target=\"_blank\">' . reduceurl(\"$3\", 30) . '</a>'", $linktext);
return $linktext;
}
29-Feb-2008 08:02
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!
14-Jan-2008 09:29
Here is my attempt at cleaning up a file name... it's similar to what someone else has done however a little cleaner with the addition of the | in the reserved characters... also I clean any characters from x00 to x40 (all non display characters and space) as well as everything greater than 7f and greater (removes the Del character and other non English characters), replacing them with an '_'.
<?php
function clean_filename($filename){//function to clean a filename string so it is a valid filename
$reserved = preg_quote('\/:*?"<>|', '/');//characters that are illegal on any of the 3 major OS's
//replaces all characters up through space and all past ~ along with the above reserved characters
return preg_replace("/([\\x00-\\x20\\x7f-\\xff{$reserved}])/e", "_", $filename);
}
?>
[EDIT BY danbrown AT php DOT net: Inserted typofix/bugfix provided by "Bryan Roach" on 15 January, 2008.]
11-Dec-2007 04:17
<?php
function repl_amp($text)
{
$text=preg_replace("/&(?!amp;)/i", "&", $text);
$text=preg_replace("/&#(\d+);/i", "&#$1;", $text); // For numeric entities
$text=preg_replace("/&(\w+);/i", "&$1;", $text); // For literal entities
return $text;
}
?>
The RegEx Tester says that the first expression is OK, but when testing with various entities, some of them came out broken. I'd tried to use only 2 preg_replace(); calls instead of three by using the alternative branch from the pattern syntax - which didn't came out well. Sorry for the previous error, and I still hope that someone can find a better alternative.
07-Dec-2007 06:28
Hi,
as I wasn't able to find another way to do this, I wrote a function converting any UTF-8 string into a correct NTFS filename (see http://en.wikipedia.org/wiki/Filename).
<?php
function strToNTFSFilename($string)
{
$reserved = preg_quote('\/:*?"<>', '/');
return preg_replace("/([\\x00-\\x1f{$forbidden}])/e", "_", $string);
}
?>
It converts all control characters and filename characters which are reserved by Windows ('\/:*?"<>') into an underscore.
This way you can safely create an NTFS filename out of any UTF-8 string.
18-Oct-2007 03:49
Hi.
Not sure if this will be a great help to anyone out there, but thought i'd post just in case.
I was having an Issue with a project that relied on $_SERVER['REQUEST_URI']. Obviously this wasn't working on IIS.
(i am using mod_rewrite in apache to call up pages from a database and IIS doesn't set REQUEST_URI). So i knocked up this simple little preg_replace to use the query string set by IIS when redirecting to a PHP error page.
<?php
//My little IIS hack :)
if(!isset($_SERVER['REQUEST_URI'])){
$_SERVER['REQUEST_URI'] = preg_replace( '/404;([a-zA-Z]+:\/\/)(.*?)\//i', "/" , $_SERVER['QUERY_STRING'] );
}
?>
Hope this helps someone else out there trying to do the same thing :)
24-Aug-2007 10:10
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
?>
21-Aug-2007 08:48
Also worth noting is that you can use array_keys()/array_values() with preg_replace like:
<?php
$subs = array(
'/\[b\](.+)\[\/b\]/Ui' => '<strong>$1</strong>',
'/_(.+)_/Ui' => '<em>$1</em>'
...
...
);
$raw_text = '[b]this is bold[/b] and this is _italic!_';
$bb_text = preg_replace(array_keys($subs), array_values($subs), $raw_text);
?>
25-Jul-2007 08:15
I got problem echoing text that contains double-quotes into a text field. As it confuses value option. I use this function below to match and replace each pair of them by smart quotes. The last one will be replaced by a hyphen(-).
It works for me.
<?php
function smart_quotes($text) {
$pattern = '/"((.)*?)"/i';
$text = preg_replace($pattern,"“\\1”",stripslashes($text));
$text = str_replace("\"","-",$text);
$text = addslashes($text);
return $text;
}
?>
17-Jul-2007 11:37
Based on previous comment, i suggest
( this function already exist in php 6 )
<?php
function unicode_decode($str){
return preg_replace(
'#\\\u([0-9a-f]{4})#e',
"unicode_value('\\1')",
$str);
}
function unicode_value($code) {
$value=hexdec($code);
if($value<0x0080)
return chr($value);
elseif($value<0x0800)
return chr((($value&0x07c0)>>6)|0xc0)
.chr(($value&0x3f)|0x80);
else
return chr((($value&0xf000)>>12)|0xe0)
.chr((($value&0x0fc0)>>6)|0x80)
.chr(($value&0x3f)|0x80);
}
?>
[EDIT BY danbrown AT php DOT net: This function originally written by mrozenoer AT overstream DOT net.]
09-Jul-2007 09:30
This function takes a URL and returns a plain-text version of the page. It uses cURL to retrieve the page and a combination of regular expressions to strip all unwanted whitespace. This function will even strip the text from STYLE and SCRIPT tags, which are ignored by PHP functions such as strip_tags (they strip only the tags, leaving the text in the middle intact).
Regular expressions were split in 2 stages, to avoid deleting single carriage returns (also matched by \s) but still delete all blank lines and multiple linefeeds or spaces, trimming operations took place in 2 stages.
<?php
function webpage2txt($url)
{
$user_agent = “Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)”;
$ch = curl_init(); // initialize curl handle
curl_setopt($ch, CURLOPT_URL, $url); // set url to post to
curl_setopt($ch, CURLOPT_FAILONERROR, 1); // Fail on errors
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // allow redirects
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // return into a variable
curl_setopt($ch, CURLOPT_PORT, 80); //Set the port number
curl_setopt($ch, CURLOPT_TIMEOUT, 15); // times out after 15s
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
$document = curl_exec($ch);
$search = array(’@<script[^>]*?>.*?</script>@si’, // Strip out javascript
‘@<style[^>]*?>.*?</style>@siU’, // Strip style tags properly
‘@<[\/\!]*?[^<>]*?>@si’, // Strip out HTML tags
‘@<![\s\S]*?–[ \t\n\r]*>@’, // Strip multi-line comments including CDATA
‘/\s{2,}/’,
);
$text = preg_replace($search, “\n”, html_entity_decode($document));
$pat[0] = “/^\s+/”;
$pat[2] = “/\s+\$/”;
$rep[0] = “”;
$rep[2] = ” “;
$text = preg_replace($pat, $rep, trim($text));
return $text;
}
?>
Potential uses of this function are extracting keywords from a webpage, counting words and things like that. If you find it useful, drop us a comment and let us know where you used it.
21-Mar-2007 05:47
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.
07-Feb-2007 07:09
Note that it is in most cases much more efficient to use preg_replace_callback(), with a named function or an anonymous function created with create_function(), instead of the /e modifier. When preg_replace() is called with the /e modifier, the interpreter must parse the replacement string into PHP code once for every replacement made, while preg_replace_callback() uses a function that only needs to be parsed once.
07-Sep-2006 09:21
Wasted several hours because of this:
<?php
$str='It's a string with HTML entities';
preg_replace('~&#(\d+);~e', 'code2utf($1)', $str);
?>
This code must convert numeric html entities to utf8. And it does with a little exception. It treats wrong codes starting with �
The reason is that code2utf will be called with leading zero, exactly what the pattern matches - code2utf(039).
And it does matter! PHP treats 039 as octal number.
Try <?php print(011); ?>
Solution:
<?php preg_replace('~�*(\d+);~e', 'code2utf($1)', $str); ?>
21-Apr-2006 12:15
For those of you that have ever had the problem where clients paste text from msword into a CMS, where word has placed all those fancy quotes throughout the text, breaking the XHTML validator... I have created a nice regular expression, that replaces ALL high UTF-8 characters with HTML entities, such as ’.
Note that most user examples on php.net I have read, only replace selected characters, such as single and double quotes. This replaces all high characters, including greek characters, arabian characters, smilies, whatever.
It took me ages to get it just downto two regular expressions, but it handles all high level characters properly.
<?php
$text = preg_replace('/([\xc0-\xdf].)/se', "'&#' . ((ord(substr('$1', 0, 1)) - 192) * 64 + (ord(substr('$1', 1, 1)) - 128)) . ';'", $text);
$text = preg_replace('/([\xe0-\xef]..)/se', "'&#' . ((ord(substr('$1', 0, 1)) - 224) * 4096 + (ord(substr('$1', 1, 1)) - 128) * 64 + (ord(substr('$1', 2, 1)) - 128)) . ';'", $text);
?>
18-Oct-2004 08:39
It is useful to note that the 'limit' parameter, when used with 'pattern' and 'replace' which are arrays, applies to each individual pattern in the patterns array, and not the entire array.
<?php
$pattern = array('/one/', '/two/');
$replace = array('uno', 'dos');
$subject = "test one, one two, one two three";
echo preg_replace($pattern, $replace, $subject, 1);
?>
If limit were applied to the whole array (which it isn't), it would return:
test uno, one two, one two three
However, in reality this will actually return:
test uno, one dos, one two three
08-Feb-2004 05:45
People using the /e modifier with preg_replace should be aware of the following weird behaviour. It is not a bug per se, but can cause bugs if you don't know it's there.
The example in the docs for /e suffers from this mistake in fact.
With /e, the replacement string is a PHP expression. So when you use a backreference in the replacement expression, you need to put the backreference inside quotes, or otherwise it would be interpreted as PHP code. Like the example from the manual for preg_replace:
preg_replace("/(<\/?)(\w+)([^>]*>)/e",
"'\\1'.strtoupper('\\2').'\\3'",
$html_body);
To make this easier, the data in a backreference with /e is run through addslashes() before being inserted in your replacement expression. So if you have the string
He said: "You're here"
It would become:
He said: \"You\'re here\"
...and be inserted into the expression.
However, if you put this inside a set of single quotes, PHP will not strip away all the slashes correctly! Try this:
print ' He said: \"You\'re here\" ';
Output: He said: \"You're here\"
This is because the sequence \" inside single quotes is not recognized as anything special, and it is output literally.
Using double-quotes to surround the string/backreference will not help either, because inside double-quotes, the sequence \' is not recognized and also output literally. And in fact, if you have any dollar signs in your data, they would be interpreted as PHP variables. So double-quotes are not an option.
The 'solution' is to manually fix it in your expression. It is easiest to use a separate processing function, and do the replacing there (i.e. use "my_processing_function('\\1')" or something similar as replacement expression, and do the fixing in that function).
If you surrounded your backreference by single-quotes, the double-quotes are corrupt:
$text = str_replace('\"', '"', $text);
People using preg_replace with /e should at least be aware of this.
I'm not sure how it would be best fixed in preg_replace. Because double-quotes are a really bad idea anyway (due to the variable expansion), I would suggest that preg_replace's auto-escaping is modified to suit the placement of backreferences inside single-quotes (which seemed to be the intention from the start, but was incorrectly applied).
23-Oct-2003 02:38
I got sick of trying to replace just a word, so I decided I would write my own string replacement code. When that code because far to big and a little faulty I decided to use a simple preg_replace:
<?php
/**
* Written by Rowan Lewis of PixelCarnage.com
* $search(string), the string to be searched for
* $replace(string), the string to replace $search
* $subject(string), the string to be searched in
*/
function word_replace($search, $replace, $subject) {
return preg_replace('/[a-zA-Z]+/e', '\'\0\' == \'' . $search . '\' ? \'' . $replace . '\': \'\0\';', $subject);
}
?>
I hope that this code helpes someone!
