Replace all occurrences using preg_replace - php

The code below works perfectly:
$string = '(test1)';
$new = preg_replace('/^\(+.+\)+$/','word',$string);
echo $new;
Output:
word
If the code is this:
$string = '(test1) (test2) (test3)';
How to generate output:
word word word?

Why my regex do not work ?
^ and $ are anchors which means match should start from start of string and expand upto end of string
. means match anything except newline, + means one or more, by default regex is greedy in nature so it tries to match as much as possible where as we want to match ( ) so we need to change the pattern a bit
You can use
\([^)]+\)
$string = '(test1) (test2) (test3)';
$new = preg_replace('/\([^)]+\)/','word',$string);
echo $new;
Regex Demo

Related

simple pattern with preg_match_ALL work fine!, how to use with preg_replace?

thanks by your help.
my target is use preg_replace + pattern for remove very sample strings.
then only using preg_replace in this string or others, I need remove ANY content into <tag and next symbol >, the pattern is so simple, then:
$x = '#<\w+(\s+[^>]*)>#is';
$s = 'DATA<td class="td1">111</td><td class="td2">222</td>DATA';
preg_match_all($x, $s, $Q);
print_r($Q[1]);
[1] => Array
(
[0] => class="td1"
[1] => class="td2"
)
work greath!
now I try remove strings using the same pattern:
$new_string = '';
$Q = preg_replace($x, "\\1$new_string", $s);
print_r($Q);
result is completely different.
what is bad in my use of preg_replace?
using only preg_replace() how I can remove this strings?
(we can use foreach(...) for remove each string, but where is the error in my code?)
my result expected when I intro this value:
$s = 'DATA<td class="td1">111</td><td class="td2">222</td>DATA';
is this output:
$Q = 'DATA<td>111</td><td>222</td>DATA';
Let's break down your RegEx, #<\w+(\s+[^>]*)>#is, and see if that helps.
# // Start delimiter
< // Literal `<` character
\w+ // One or more word-characters, a-z, A-Z, 0-9 or _
( // Start capturing group
\s+ // One or more spaces
[^>]* // Zero or more characters that are not the literal `>`
) // End capturing group
> // Literal `>` character
# // End delimiter
is // Ignore case and `.` matches all characters including newline
Given the input DATA<td class="td1">DATA this matches <td class="td1"> and captures class="td1". The difference between match and capture is very important.
When you use preg_match you'll see the entire match at index 0, and any subsequent captures at incrementing indexes.
When you use preg_replace the entire match will be replaced. You can use the captures, if you so choose, but you are replacing the match.
I'm going to say that again: whatever you pass as the replacement string will replace the entirety of the found match. If you say $1 or \\=1, you are saying replace the entire match with just the capture.
Going back to the sample after the breakdown, using $1 is the equivalent of calling:
str_replace('<td class="td1">', ' class="td1"', $string);
which you can see here: https://3v4l.org/ZkPFb
To your question "how to change [0] by $new_string", you are doing it correctly, it is your RegEx itself that is wrong. To do what you are trying to do, your pattern must capture the tag itself so that you can say "replace the HTML tag with all of the attributes with just the tag".
As one of my comments noted, this is where you'd invert the capturing. You aren't interesting in capturing the attributes, you are throwing those away. Instead, you are interested in capturing the tag itself:
$string = 'DATA<td class="td1">DATA';
$pattern = '#<(\w+)\s+[^>]*>#is';
echo preg_replace($pattern, '<$1>', $string);
Demo: https://3v4l.org/oIW7d

Regex rules in an array

Maybe it can not be solved this issue as I want, but maybe you can help me guys.
I have a lot of malformed words in the name of my products.
Some of them has leading ( and trailing ) or maybe one of these, it is same for / and " signs.
What I do is that I am explode the name of the product by spaces, and examines these words.
So I want to replace them to nothing. But, a hard drive could be 40GB ATA 3.5" hard drive. I need to process all the word, but I can not use the same method for 3.5" as for () or // because this 3.5" is valid.
So I only need to replace the quotes, when it is at the start of the string AND at end of the string.
$cases = [
'(testone)',
'(testtwo',
'testthree)',
'/otherone/',
'/othertwo',
'otherthree/',
'"anotherone',
'anothertwo"',
'"anotherthree"',
];
$patterns = [
'/^\(/',
'/\)$/',
'~^/~',
'~/$~',
//Here is what I can not imagine, how to add the rule for `"`
];
$result = preg_replace($patterns, '', $cases);
This is works well, but can it be done in one regex_replace()? If yes, somebody can help me out the pattern(s) for the quotes?
Result for quotes should be this:
'"anotherone', //no quote at end leave the leading
'anothertwo"', //no quote at start leave the trailin
'anotherthree', //there are quotes on start and end so remove them.
You may use another approach: rather than define an array of patterns, use one single alternation based regex:
preg_replace('~^[(/]|[/)]$|^"(.*)"$~s', '$1', $s)
See the regex demo
Details:
^[(/] - a literal ( or / at the start of the string
| - or
[/)]$ - a literal ) or / at the end of the string
| - or
^"(.*)"$ - a " at the start of the string, then any 0+ characters (due to /s option, the . matches a linebreak sequence, too) that are captured into Group 1, and " at the end of the string.
The replacement pattern is $1 that is empty when the first 2 alternatives are matched, and contains Group 1 value if the 3rd alternative is matched.
Note: In case you need to replace until no match is found, use a preg_match with preg_replace together (see demo):
$s = '"/some text/"';
$re = '~^[(/]|[/)]$|^"(.*)"$~s';
$tmp = '';
while (preg_match($re, $s) && $tmp != $s) {
$tmp = $s;
$s = preg_replace($re, '$1', $s);
}
echo $s;
This works
preg_replace([[/(]?(.+)[/)]?|/\"(.+)\"/], '$1', $string)

Removing all characters and numbers except last variable with dash symbol

Hi I want to remove a characters using preg_replace in php so i have this code here which i want to remove the whole characters, letters and numbers except the last digit(s) which has dash(-) symbol followed by a digits so here's my code.
echo preg_replace('/(.+)(?=-[0-9])|(.+)/','','asdf1245-10');
I expect the result will be
-10
the problem is above is not working very well. I checked the pattern using http://www.regextester.com/ it seems like it works, but on the other side http://www.phpliveregex.com/ doesn't work at all. I don't know why but anyone who can help to to figure it out?
Thanks a lot
Here is a way to go:
echo preg_replace('/^.+?(-[0-9]+)?$/','$1','asdf1245-10');
Output:
-10
and
echo preg_replace('/^.+?(-[0-9]+)?$/','$1','asdf124510');
Output:
<nothing>
My first thinking is to use explode in this case.. make it simple like the following code.
$string = 'asdf1245-10';
$array = explode('-', $string);
end($array);
$key = key($array);
$result = '-' . $array[$key];
$result => '-10';
An other way:
$result = preg_match('~\A.*\K-\d+\z~', $str, $m) ? $m[0] : '';
pattern details:
\A # start of the string anchor
.* # zero or more characters
\K # discard all on the left from match result
-\d+ # the dash and the digits
\z # end of the string anchor
echo preg_replace('/(\w+)(-\w+)/','$2', 'asdf1245-10');

How to manipulate a string so I can make implicit multiplication explicit in a math expression?

I want to manipulate a string like "...4+3(4-2)-...." to become "...4+3*(4-2)-....", but of course it should recognize any number, d, followed by a '(' and change it to 'd*('. And I also want to change ')(' to ')*(' at the same time if possible. Would nice if there is a possibility to add support for constants like pi or e too.
For now, I just do it this stupid way:
private function make_implicit_multiplication_explicit($string)
{
$i=1;
if(strlen($string)>1)
{
while(($i=strpos($string,"(",$i))!==false)
{
if(strpos("0123456789",substr($string,$i-1,1)))
{
$string=substr_replace($string,"*(",$i,1);
$i++;
}
$i++;
}
$string=str_replace(")(",")*(",$string);
}
return $string;
}
But I Believe this could be done much nicer with preg_replace or some other regex function? But those manuals are really cumbersome to grasp, I think.
Let's start by what you are looking for:
either of the following: ((a|b) will match either a or b)
any number, \d
the character ): \)
followed by (: \(
Which creates this pattern: (\d|\))\(. But since you want to modify the string and keep both parts, you can group the \( which results in (\() making it worse to read but better to handle.
Now everything left is to tell how to rearrange, which is simple: \\1*\\2, leaving you with code like this
$regex = "/(\d|\))(\()/";
$replace = "\\1*\\2";
$new = preg_replace($regex, $replace, $test);
To see that the pattern actually matches all cases, see this example.
To recognize any number followed by a ( OR a combination of a )( and place an asterisk in between them, you can use a combination of lookaround assertions.
echo preg_replace("/
(?<=[0-9)]) # look behind to see if there is: '0' to '9', ')'
(?=\() # look ahead to see if there is: '('
/x", '*', '(4+3(4-2)-3)(2+3)');
The Positive Lookbehind asserts that what precedes is either a number or right parentheses. While the Positive Lookahead asserts that the preceding characters are followed by a left parentheses.
Another option is to use the \K escape sequence in replace of the Lookbehind. \K resets the starting point of the reported match. Any previously consumed characters are no longer included ( throws away everything that it has matched up to that point. )
echo preg_replace("/
[0-9)] # any character of: '0' to '9', ')'
\K # resets the starting point of the reported match
(?=\() # look ahead to see if there is: '('
/x", '*', '(4+3(4-2)-3)(2+3)');
Your php code should be,
<?php
$mystring = "4+3(4-2)-(5)(3)";
$regex = '~\d+\K\(~';
$replacement = "*(";
$str = preg_replace($regex, $replacement, $mystring);
$regex1 = '~\)\K\(~';
$replacement1 = "*(";
echo preg_replace($regex1, $replacement1, $str);
?> //=> 4+3*(4-2)-(5)*(3)
Explanation:
~\d+\K\(~ this would match the one or more numbers followed by a (. Because of \K it excludes the \d+
Again it replaces the matched part with *( which in turn produces 3*( and the result was stored in another variable.
\)\K\( Matches )( and excludes the first ). This would be replaced by *( which in turn produces )*(
DEMO 1
DEMO 2
Silly method :^ )
$value = '4+3(4-2)(1+2)';
$search = ['1(', '2(', '3(', '4(', '5(', '6(', '7(', '8(', '9(', '0(', ')('];
$replace = ['1*(', '2*(', '3*(', '4*(', '5*(', '6*(', '7*(', '8*(', '9*(', '0*(', ')*('];
echo str_replace($search, $replace, $value);

PHP regular expression find and append to string

I'm trying to use regular expressions (preg_match and preg_replace) to do the following:
Find a string like this:
{%title=append me to the title%}
Then extract out the title part and the append me to the title part. Which I can then use to perform a str_replace(), etc.
Given that I'm terrible at regular expressions, my code is failing...
preg_match('/\{\%title\=(\w+.)\%\}/', $string, $matches);
What pattern do I need? :/
I think it's because the \w operator doesn't match spaces. Because everything after the equal sign is required to fit in before your closing %, it all has to match whatever is inside those brackets (or else the entire expression fails to match).
This bit of code worked for me:
$str = '{%title=append me to the title%}';
preg_match('/{%title=([\w ]+)%}/', $str, $matches);
print_r($matches);
//gives:
//Array ([0] => {%title=append me to the title%} [1] => append me to the title )
Note that the use of the + (one or more) means that an empty expression, ie. {%title=%} won't match. Depending on what you expect for white space, you might want to use the \s after the \w character class instead of an actual space character. \s will match tabs, newlines, etc.
You can try:
$str = '{%title=append me to the title%}';
// capture the thing between % and = as title
// and between = and % as the other part.
if(preg_match('#{%(\w+)\s*=\s*(.*?)%}#',$str,$matches)) {
$title = $matches[1]; // extract the title.
$append = $matches[2]; // extract the appending part.
}
// find these.
$find = array("/$append/","/$title/");
// replace the found things with these.
$replace = array('IS GOOD','TITLE');
// use preg_replace for replacement.
$str = preg_replace($find,$replace,$str);
var_dump($str);
Output:
string(17) "{%TITLE=IS GOOD%}"
Note:
In your regex: /\{\%title\=(\w+.)\%\}/
There is no need to escape % as its
not a meta char.
There is no need to escape { and }.
These are meta char but only when
used as a quantifier in the form of
{min,max} or {,max} or {min,}
or {num}. So in your case they are treated literally.
Try this:
preg_match('/(title)\=(.*?)([%}])/s', $string, $matches);
The match[1] has your title and match[2] has the other part.

Categories