PHP: PCRE: how to replace repeatable char

For example, I have the following line:

a_b__c___d____e 

Like preg_replace char _ to char '-', but only if the '__...' part contains more than N repetitions of _.

I hope you got what I meant))

 source: a_b__c___d____e cond: change '_' where 2 or more result: a_b--c---d----e 

or

 source: a_b__c___d____e_____f cont: change '_' where 4 or more result: a_b__c___d----e-----f 

Thanks!

ps An interesting solution without using loops. How to implement it using loops (I think) know someone. Only one regex and preg_replace.

+6
source share
4 answers

Here is another e modifier:

  $str = 'a_b__c___d____e_____f'; echo preg_replace('/_{4,}/e', 'str_repeat("-", strlen("$0"))', $str); 

Replace 4 with the number you need. Or as a function:

 function repl($str, $char, $times) { $char = preg_quote($char, '/'); $times = preg_quote($times, '/'); $pattern = '/' . $char . '{' . $times . ',}/e', return preg_replace($pattern, 'str_repeat("-", strlen("$0"))', $str); } 
+2
source
 $source = 'a_b__c___d____e_____f'; function yourfunc($param) { $count = strlen($param); $return = ''; for ($i = 0; $i < $count; $i++) { $return .= '-'; } return $return; } echo preg_replace('#(_{4,})#e', 'yourfunc("$1");', $source); 

A solution without a callback and loop function is much harder to read.

 preg_replace('#(_{4,})#e', 'implode("", array_pad(array(), strlen("$1"), "-"));', $source); 
+1
source

this is a built-in solution:

 preg_replace('/(_{2,})/ie', 'str_repeat("-",strlen("$1"));', $source); 

and reusable function:

 $source = 'a_b__c___d____e_____f'; function replace_repeatable($source,$char,$replacement,$minrepeat = 2) { return preg_replace('/(' . preg_quote($char) . '{' . $minrepeat . ',})/ie', 'str_repeat("' . $replacement . '",strlen("$1"));', $source); } $b = replace_repeatable($source,'_','-',4); 
+1
source

As php.net refers to documenation using the e modifier is not recommended,

This function has been DEPRECATED since PHP 5.5.0. Based on this feature, it is highly discouraged.

therefore, we better achieve our goal without using this modifier.


Here the solution is based on modern PHP tools:

 $source = 'a_b__c___d____e'; echo preg_replace_callback( "%(_{2,})%i", function($matches) {return str_repeat( "-", strlen($matches[1]) ); }, $source ); /* in callback function matches[0] is whole matched pattern, groups go like this matches[1],matches[2]... */ 

Even with e , which is still available in our PHP environment, it is usually better to use a callback function - thanks to the callback, we avoid the rather insecure combination of the addslashes() function and the string evaluation, since running preg_replace with the specified modifier involves both actions at that time.


A preg_replace_callback available since version 4.0.5, but function($matches) {} is an anonymous function, which is actually a much newer language function, to run this code you need PHP in version 5.3.0 or later .

0
source

Source: https://habr.com/ru/post/888316/


All Articles