I'm trying to build a regex that will use preg_replace to quote the right side of an expression if it's unquoted.
So myvar = 3 becomes myvar = '3'. It should only deal with unquoted strings that are contiguous (so if there any spaces on the first string need be quoted e.g. myvar = 3 5 will become myvar = '3' 5).
I also want it to ignore any quoted string, so myvar = 'this is quoted' should not be modified.
So far I have the code below:
$str = 'myvar = 3';
$regex = '/([\w\#\-]+) *(\=|\>|\>\=|\<|\<\=) *([\w]+)/i';
$replace = '\1 \2 \'\3\'';
$result = preg_replace($regex, $replace_str, $str);
What do I need to put in $regex to make this work?
You could use preg_replace_callback, or maybe this could work (right side of the regex only):
#([^\'\"])(\w+)([^\'\"])#
And replace like this:
$exp = '#([^\'\"])(\w+)([^\'\"])#';
$str = 'This is unquoted';
$quoted = preg_replace($exp, '\'$1$2$3\'', $str); // should hopefully be 'This is unquoted' after. Not tested.
It's kind of a hacky work-around though.
EDIT:
Yeah, no-go. I'd recommend preg_replace_callback then.
I eventually settled for the following:
$str = 'myvar = 3';
$regex = '/([\w\#\-]+) *(\=|\>|\>\=|\<|\<\=) *([^\s\']+)/i';
$replace = '\1 \2 \'\3\'';
$result = preg_replace($regex, $replace_str, $str);
I needed this as one step of a multi-step operation so I wanted to use this regex in question to bake an uber regex that would do everything in one go. However, it turns out preg_replace can also be fed 'search' and 'replace' arrays, so I went with that for my final solution. It's much easier to grasp that way as well.
Cheers.
Related
I have a query string that may look like one of the following:
?key=aa=bb
?key=aa=bb=cc
?key=aa=bb&key2=cc
etc.
What I want to do is replace the equal sign in the value part only. So it should result in this:
?key=aa%3dbb
?key=aa%3dbb%3dcc
?key=aa%3dbb&key2=cc
I'm trying to do that with the following regex by using a look ahead. But it's not doing anything.
echo preg_replace("/=(?=[^&])=/", "%3d", 'http://www.example.com?key=aaa=bbb=ccc&key3=dddd');
Example code here
How can I make this work?
(\bkey\d*)=(*SKIP)(*F)|=
Try this.See demo.
https://regex101.com/r/hR7tH4/13
$re = "/(\\bkey\\d*)=(*SKIP)(*F)|=/m";
$str = "\n ?key=aa=bb\n ?key=aa=bb=cc\n ?key=aa=bb&key2=cc\n";
$subst = "%3d";
$result = preg_replace($re, $subst, $str);
You don't need regex, use the proper tools. parse_url() to get the query string (and whatever else you want), then parse_str() to get an array of the var/vals. Then http_build_query() will encode for you:
$query = parse_url('http://www.example.com?key=aaa=bbb=ccc&key3=dddd', PHP_URL_QUERY);
parse_str($query, $array);
$result = http_build_query($array);
Here is another version of a regex based on the same approach as vks':
[&?][^&=]+=(*SKIP)(*FAIL)|=
Regex explanation:
[&?] - Match & or ? literally
[^&=]+ - Match characters other than & and =
= - Match = (so, we matched a key)
(*SKIP)(*FAIL) - Verbs that fail the match at this point (we do not replace this = we found after key)
= - We match any other = and we'll remove it.
Here is IDEONE demo:
$re = "/[&?][^&=]+=(*SKIP)(*FAIL)|=/";
$str = "http://google.com?key=aa=bb\nhttp://google.com?key=aa=bb=cc\nhttp://google.com?key=aa=bb&key2=cc";
$result = preg_replace($re, "%3d", $str);
echo $result;
What about this?
preg_replace_callback("/=([^&$]+)/", "myReplace", "http://www.example.com?key=aaa=bbb=ccc&key3=dddd");
function myReplace($matches) {
return "=" . urlencode($matches[1]);
}
Just gonna add an addendum, explaining your specific attempt:
preg_replace("/=(?=[^&])=/",
↑ ↑
While the lookahead was a nice idea, it really just would match a single character. And in this case just would have asserted the very next character not to be &.
You could refashion it into:
preg_replace("/=([^&=]+)\K=/",
↑
Which I guess is what you tried. Note that this merely ignores every second =………= equal sign. So would only suit your simple example query strings, not more plentiful unescaped characters within.
I would like to accept in string PHP only letters and change all spaces for plus (+) character. Further I would like to accept only one plus next to each other. So this string:
$string = 'ex,a-mpl*e s++tri ng';
sholud replace for:
$string = 'example+s+tri+ng';
I tried like that:
#[^a-zA-Z0-9\+\]#
but that isn't helpful for me.
Can you help me? :)
EDIT:
aahh, and I would like to also accept only strings where string's lenth is 3 or more.
Try if something like this could be a good starting point:
$string = 'ex,a-mpl*e s++tri ng';
$pattern = array(
'/([^a-zA-Z\+\s])/',
'/(\+|\s)+/'
);
$replacement = array('', '+');
$result = preg_replace($pattern, $replacement, (strlen($string) > 3) ? $string : false);
var_dump($result); //<- return an empty string if the length is < 3
Just letters and digits
You got your regex already, just use it
$str = preg_replace('#[^a-zA-Z0-9\+\]#', '', $str);
Replace Spaces, strip multiple ones
$str = preg_replace('/\s+/', '+', $str);
How to solve such things
I don't want to be rude but the code I pasted, is just a slightly change of Example #4 from here http://us2.php.net/en/preg_replace
So please questions like this are very common and php.net really does a good job with putting examples together. So try to search there first!
I need to extract a project number out of a string. If the project number was fixed it would have been easy, however it can be either P.XXXXX, P XXXXX or PXXXXX.
Is there a simple function like preg_match that I could use? If so, what would my regular expression be?
There is indeed - if this is part of a larger string e.g. "The project (P.12345) is nearly done", you can use:
preg_match('/P[. ]?(\d{5})/',$str,$match);
$pnumber = $match[1];
Otherwise, if the string will always just be the P.12345 string, you can use:
preg_match('/\d{5}$/',$str,$match);
$pnumber = $match[0];
Though you may prefer the more explicit match of the top example.
Try this:
if (preg_match('#P[. ]?(\d{5})#', $project_number, $matches) {
$project_version = $matches[1];
}
Debuggex Demo
You said that project number is 4 of 5 digit length, so:
preg_match('/P[. ]?(\d{4,5})/', $tring, $m);
$project_number = $m[1];
Assuming you want to extract the XXXXX from the string and XXXXX are all integers, you can use the following.
preg_replace("/[^0-9]/", "", $string);
You can use the ^ or caret character inside square brackets to negate the expression. So in this instance it will replace anything that isn't a number with nothing.
I would use this kind of regex : /.*P[ .]?(\d+).*/
Here is a few test lines :
$string = 'This is the P123 project, with another useless number 456.';
$project = preg_replace('/.*P[ .]?(\d+).*/', '$1', $string);
var_dump($project);
$string = 'This is the P.123 project, with another useless number 456.';
$project = preg_replace('/.*P[ .]?(\d+).*/', '$1', $string);
var_dump($project);
$string = 'This is the P 123 project, with another useless number 456.';
$project = preg_replace('/.*P[ .]?(\d+).*/', '$1', $string);
var_dump($project);
use explode() function to split those
I have a URL like this:
http://Example.com/mobile-ds-cams/mobile-gg-cams/ddd-webcams
Example:
$pattern = '/http://Example.com/(\w+)/(\w+)/(\w+)/i';
$replacement="http://Example.com/$2/$3";
$appUrl= preg_replace($pattern, $replacement, $appUrl);
What I want to achieve is this
http://Example.com/mobile-gg-cams/ddd-webcams
I am trying to keep 2 "sub-URLs" instead of 3. but it doesn't work..why?
You need to escape your forward-slashes within the pattern, or use different pattern delimiters.
$pattern = '/http:\/\/Example\.com\/(\w+)\/(\w+)\/(\w+)/i';
$pattern = '#http://Example\.com/(\w+)/(\w+)/(\w+)#i';
It doesn't work correctly because your expression contains characters with special meaning in a regex that have not been properly quoted.
To be 100% certain, use preg_quote like this:
$url = 'http://Example.com/'
$pattern = preg_quote($url.'{word}/{word}/{word}', '/');
$pattern = str_replace($pattern, '{word}', '(\w+)');
$pattern = "/$pattern/i";
$replacement = $url.'$2/$3';
$appUrl= preg_replace($pattern, $replacement, $appUrl);
Otherwise, it's simply too easy to get things wrong. For example, all of the other answers currently posted here get it wrong because they do not properly escape the . in Example.com. You can test this yourself if you feed them a string like e.g. http://Example!com, where ! can be any character you like.
Additionally, you are using strings such as $2 inside a double-quoted string literal, which is not a good idea in PHP because IMHO it's easy to get carried away. Better make that singly quoted and be safe.
Escape the slashes like this:
$pattern = '/http:\/\/Example.com\/(\w+)\/(\w+)\/(\w+)/i';
$replacement="http://Example.com/$2/$3";
$appUrl= preg_replace($pattern, $replacement, $appUrl);
Say I have strings: "Sports Car (45%)", or "Truck (50%)", how can I convert them to "Sports_Car" and "Truck".
I know about str_replace or whatever but how do I clip the brackets and numbers part off the end? That's the part I'm struggling with.
You can do:
$s = "Sports Car (45%)";
$s = preg_replace(array('/\([^)]*\)/','/^\s*|\s*$/','/ /'),array('','','_'),$s);
See it
There are a few options here, but I would do one of these:
// str_replace() the spaces to _, and rtrim() numbers/percents/brackets/spaces/underscores
$result = str_replace(' ','_',rtrim($str,'01234567890%() _'));
or
// Split by spaces, remove the last element and join by underscores
$split = explode(' ',$str);
array_pop($split);
$result = implode('_',$split);
or you could use one of a thousand regular expression approaches, as suggested by the other answers.
Deciding which approach to use depends on exactly how your strings are formatted, and how sure you are that the format will always remain the same. The regex approach is potentially more complicated but could afford finer-grained control in the long term.
A simple regex should be able to achieve that:
$str = preg_replace('#\([0-9]+%\)#', '', $str);
Of course, you could also choose to use strstr() to look for the (
You can do that using explode:
<?php
$string = "Sports Car (45%)";
$arr = explode(" (",$string);
$answer = $arr[0];
echo $answer;
?>