How to remove unneeded parenthesis in a string? - php

I have a string containing a mathematical expression, like (21)*(4+2). For the purposes of computing, I need to "simplify" it so that it doesn't contain any number between expression (i.e. (21)*(4+2) => 21*(4+2)). I have no idea of how to do it (I thought of something with regex replaces, but I'm not very good at handling it).

you can do an algorithm something like this:
$str = "(21)*(4+2)";
//split above to array of characters
$arr = str_split($str);
foreach($arr as $i => $char) {
if character is opening parenthesis {
get all characters in a string until closing parnethesis is found
endif }
if the string you received from above contains only digits
(means it has no expression i.e. +,-,/,%,*) then remove the first and last
characters of the above string which are the parenthesis and append the
string to the final string.
}

Okay, it seems to me that I accidently solved the problem(so far, the preg_replace works for me):
echo preg_replace( "/\((\d+)\)/", "$1", $eq );
It doesn't take into account the decimals, I think. The sample equation and output it generates is here on codepad.
For decimals, I used a [\d\.]+ in the regex. It seems to be working.
echo preg_replace( "/\(([\d\.]+)\)/", "$1", $eq );
Another link.

Related

Suggestion about search coincidences in string with PHP using REGEX

I am trying to search this coincidence in a string:
1. I need to take only numbers after the chracter '#' as long as this coincidence has not spaces, for example:
String = 'This is a test #VVC345RR, text, and more text 12345';
I want to take only this from my string -> 345.
My example:
$s = '\"access_token=103782364732640461|2. myemail#domain1.com ZmElnDTiZlkgXbT8e3 #DD234 4Jrw__.3600.1281891600-10000186237005';
$matches = array();
$s = preg_match('/#([0-9]+)/', $s, $matches);
print_r($matches);
This only works when I have one # and numbers.
Thanks!
Maybe:
#\D*\K(\d+)
Accomplishes what you want?
This will look for an #, any non-numbers, and then capture the numbers. The \K ignores the early match.
https://regex101.com/r/gNTccx/1/
I'm unclear what you mean by has not spaces, there are no spaces in the example string.

Expecting output is not displaying from php code

This is the code:
<?php
$pattern =' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
$text = "kdaiuyq7e611422^^$^vbnvcn^vznbsjhf";
$text_split = str_split($text,1);
$data = '';
foreach($text_split as $value){
if (preg_match("/".$value."/", $pattern )){
$data = $data.$value;
}
if (!preg_match('/'.$value.'/', $pattern )){
break;
}
}
echo $data;
?>
Current output:
kdaiuyq7e611422^^$^vbnvcn^vznbsjhf
Expected output:
kdaiuyq7e611422
Please help me editing my code error. In pattern there is no ^ or $. But preg_match is showing matched which is doubtful.
You string $text have ^ which will match the begin of the string $pattern.
So the preg_match('/^/', $pattern) will return true, then the ^ will append to $data.
You should escape the ^ as a raw char, not a special char with preg_match('/\^/', $pattern) by the help of preg_quote() which will escape the special char.
There is no need to split your string up like that, the whole point of a regular expression is you can specify all the conditions within the expression. You can condense your entire code down to this:
$pattern = '/^[[:word:] ]+/';
$text = 'kdaiuyq7e611422^^$^vbnvcn^vznbsjhf';
preg_match($pattern, $text, $matches);
echo $matches[0];
Kris has accurately isolated that escaping in your method is the monkey wrench. This can be solved with preg_quote() or wrapping pattern characters in \Q ... \E (force characters to be interpreted literally).
Slapping that bandaid on your method (as you have done while answering your own question) doesn't help you to see what you should be doing.
I recommend that you do away with the character mask, the str_split(), and the looped calls of preg_match(). Your task can be accomplished far more briefly/efficiently/directly with a single preg_match() call. Here is the clean way that obeys your character mask fully:
Code: (Demo)
$text = "kdaiuyq7e611422^^$^vbnvcn^vznbsjhf";
echo preg_match('/^[a-z\d ]+/i',$text,$out)?$out[0]:'No Match';
Output:
kdaiuyq7e611422
miknik's method was close to this, but it did not maintain 100% accuracy given your question requirements. I'll explain:
[:word:] is a POSIX Character Class (functioning like \w) that represents letters(uppercase and lowercase), numbers, and an underscore. Unfortunately for miknik, the underscore is not in your list of wanted characters, so this renders the pattern slightly inaccurate and may be untrustworthy for your project.

Get integer value from malformed query string

I'm looking for an way to parse a substring using PHP, and have come across preg_match however I can't seem to work out the rule that I need.
I am parsing a web page and need to grab a numeric value from the string, the string is like this
producturl.php?id=736375493?=tm
I need to be able to obtain this part of the string:
736375493
$matches = array();
preg_match('/id=([0-9]+)\?/', $url, $matches);
This is safe for if the format changes. slandau's answer won't work if you ever have any other numbers in the URL.
php.net/preg-match
<?php
$string = "producturl.php?id=736375493?=tm";
preg_match('~id=(\d+)~', $string, $m );
var_dump($m[1]); // $m[1] is your string
?>
$string = "producturl.php?id=736375493?=tm";
$number = preg_replace("/[^0-9]/", '', $string);
Unfortunately, you have a malformed url query string, so a regex technique is most appropriate. See what I mean.
There is no need for capture groups. Just match id= then forget those characters with \K, then isolate the following one or more digital characters.
Code (Demo)
$str = 'producturl.php?id=736375493?=tm';
echo preg_match('~id=\K\d+~', $str, $out) ? $out[0] : 'no match';
Output:
736375493
For completeness, there 8s another way to scan the formatted string and explicitly return an int-typed value. (Demo)
var_dump(
sscanf($str, '%*[^?]?id=%d')[0]
);
The %*[^?] means: greedily match one or more non-question mark characters, but do not capture the substring. The remainder of the format parameter matches the literal sequence ?id=, then greedily captures one or more numbers. The returned value will be cast as an integer because of the %d placeholder.

Identifying a random repeating pattern in a structured text string

I have a string that has the following structure:
ABC_ABC_PQR_XYZ
Where PQR has the structure:
ABC+JKL
and
ABC itself is a string that can contain alphanumeric characters and a few other characters like "_", "-", "+", "." and follows no set structure:
eg.qWe_rtY-asdf or pkl123
so, in effect, the string can look like this:
qWe_rtY-asdf_qWe_rtY-asdf_qWe_rtY-asdf+JKL_XYZ
My goal is to find out what string constitutes ABC.
I was initially just using
$arrString = explode("_",$string);
to return $arrString[0] before I was made aware that ABC ($arrString[0]) itself can contain underscores, thus rendering it incorrect.
My next attempt was exlpoding it on "_" anyway and then comparing each of the exploded string parts with the first string part until I get a semblance of a pattern:
function getPatternABC($string)
{
$count = 0;
$pattern ="";
$arrString = explode("_", $string);
foreach($arrString as $expString)
{
if(strcmp($expString,$arrString[0])!==0 || $count==0)
{
$pattern = $pattern ."_". $arrString[$count];
$count++;
}
else break;
}
return substr($pattern,1);
}
This works great - but I wanted to know if there was a more elegant way of doing this using regular expressions?
Here is the regex solution:
'^([a-zA-Z0-9_+-]+)_\1_\1\+'
What this does is match (starting from the beginning of the string) the longest possible sequence consisting of the characters inside the square brackets (edit that per your spec). The sequence must appear exactly twice, each time followed by an underscore, and then must appear once more followed by a plus sign (this is actually the first half of PQR with the delimiter before JKL). The rest of the input is ignored.
You will find ABC captured as capture group 1.
So:
$input = 'qWe_rtY-asdf_qWe_rtY-asdf_qWe_rtY-asdf+JKL_XYZ';
$result = preg_match('/^([a-zA-Z0-9_+-]+)_\1_\1\+/', $input, $matches);
if ($result) {
echo $matches[2];
}
See it in action.
Sure, just make a regular expression that matches your pattern. In this case, something like this:
preg_match('/^([a-zA-Z0-9_+.-]+)_\1_\1\+JKL_XYZ$/', $string, $match);
Your ABC is in $match[1].
If the presence of underscores in these strings has a low frequency, it may be worth checking to see if a simple explode() will do it before bothering with regex.
<?php
$str = 'ABC_ABC_PQR_XYZ';
if(substr_count($str, '_') == 3)
$abc = reset(explode('_', $str));
else
$abc = regexy_function($str);
?>

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