preg_replace not working as expected replacing backslashes? - php

I was using the delimiters described in this answer:
Here is shell php I'm using to demonstrate the problem:
I'm using a function on a web project that replaces a namespace syntax for a path, eg:
\org\project\namespace\access
should be converted to:
/org/project/namespace/access
But I tried many ways, some threw the following warning:
Warning: preg_replace(): No ending delimiter '/' found in...
Which I don't want to show.
The warning above shows when using this as regex: /\\/
extra: (please look at the image) why it shows a bad encoded string?
UPDATE: why does it not work as this PHP Live Regex ?

You need to use "/\\\\/" instead of "/\\/" because \\ will produce \ (a single backslash) in a PHP string literal.
See http://php.net/manual/en/language.types.string.php
Why are you using regular expressions for such simple case? Stick to str_replace() or strtr():
echo strtr($str, ['\\' => '/']);

Related

PHP urlencode issue with a parameter in my string: "&notify_url" incorrectly returns "¬ify_url"

So when I use PHP's urlencode on the following string, there seems to be a technicality coming up which I think is on a reserved PHP word "&not".
The original string:
cancel_url=https://example.com/payment_cancelled&notify_url=https://example.com/order_notify
I get the following result using urlencode:
cancel_url=https%3A%2F%2Fexample.com%2Fpayment_cancelled¬ify_url=https%3A%2F%2Fexample.com%2Forder_notify
As you notice above, the '¬' special character it creates (just after the word 'cancelled'). So to me it seems the "&not" portion of "&notify_url" is an operator reserved operator word ("&not" in PHP?).
I have tried PHP's str_replace function after url encoding as follows:
$paramUrlString = str_replace('¬', '&not', $paramUrlString);
$paramUrlString = str_replace('&#170', '&not', $paramUrlString);
(trying the ASCII code for that special character too)
I've run out of ideas now. Please assist, thank you.
urlencode does not usually replace &not at all, but does replace & with %26. See example here: http://sandbox.onlinephpfunctions.com/code/e9d62797d01f8162170e5ad5181e14fc339faa52
You could try replacing & with %26 before urlencode.
$urlString = str_replace('&', '%26', $urlString);
It's not that anything in PHP is replacting the string &not with ¬, it's that whatever you're using to view/display the data is doing that.
Given that the closing ; on the entity is not required, I would wager that you're putting the URL into XML without properly escaping the entities. While & is the entity that conflicts between URLs and XML, there are more than that.
The simplest solution is if you're embedding a raw string in an XML document you need to call:
$string = htmlspecialchars($string, ENT_XML1 | ENT_COMPAT);
The best solution, on the other hand, is to not create XML documents by hand at all. Use a library like DOMDocument or XMLWriter. This handles not only the escaping/encoding of your data, but all of the other subtle complexities of creatings proper XML documents.

preg_replace a string that contains vertical line/pipe character

I have strings like this:
$str1="YESYES|c|no|c|";
$str2="YESYES|c|not this|c|YES|c|or this|c|";
$str3="YES";
I want strings like this:
$str1="YESYES";
$str2="YESYESYES";
$str3="YES";
I thought I could use preg_replace but the fact that I'm looking at a pipe seems to cause trouble, if I go like this:
$i=preg_replace("//|c\|[\s\S]+?/|c\|/",'',$i);
I get an 'unknown modifier "|"' error. I know this must have been asked before but it's very hard to search for. What is the proper regex to use?
You have to use the next line:
$i=preg_replace("/\|c\|[\s\S]+?\|c\|/",'',$i);
which is almost identical to what you have, but using \ instead of / to scape the pipes

Differences in backslashing between Notepad++ and PHP

EDIT: I found a solution I didn't expect. See below.
Using regex via PHP's preg_match_all , I want to match a certain url (EDIT: that is already escaped) in a string formatted as json. The search works wonderfully in Notepad++ (using regex-matching, of course) but preg_match_all() just returns an empty array.
Testing on tryphpregex.com I found out that somehow my usual approach to escaping a backslash gives a pattern error, i.e. even the simple pattern https:\\ returns an empty result.
I'm utterly confused and have been trying to debug for too long so I may miss the obvious. Maybe one of you can see the simple error?
The string.
The pattern (that works fine in Notepad++, but not in PHP):
%(https:\\/\\/play.spotify.com\\/track\\/)(.*?)(\")%
You don't need to escape the slash in PHP %(https://play.spotify.com/track/)(.*?)(\")%
The Backslash before doule quote is only needed if you enclosures are double quotes too.
Found a solution to my problem.
According to this site, I need to match every backslash with \\\\. Horrible, but true.
So my pattern becomes:
$pattern = "%(https:\\\\/\\\\/play\.spotify\.com\\\\/track\\\\/)(.*?)(\")%";
Please observe that I tried to find a pattern inside a string that didn't contain clear urls, but urls containing escape characters (it was a json-output from spotify)

preg_replace(), no ending delimiter '$' found

Alright, this problem seems to be way above my head!
I have this code:
$request=preg_replace('$(^'.str_replace('$','\$',$webRoot).')$i','',$requestUri);
This throws me an error:
preg_replace(): No ending delimiter '$' found
But here's the thing, that ending delimeter is certainly there.
After that function call I echoed out the following:
echo $webRoot;
echo $requestUri;
echo '$(^'.str_replace('$','\$',$webRoot).')$i';
This is the result of those echoes:
/
/en/example/
$(^/)$i
What is funny is that if I do this directly:
preg_replace('$(^/)$i','',$requestUri);
..it works. But this also fails:
$tmp=str_replace('$','\$',$webRoot);
preg_replace('$(^'.$tmp.')$i','',$requestUri);
And just to be thorough, I also tested what echo $tmp gives, and it does give the proper value:
/
Is it a bug in PHP in Windows? I tried it out on Linux server and it worked as expected, it didn't throw this error. Or am I missing something?
Just to make sure, I even updated PHP to latest Windows version (5.4.2) and the same thing happens.
Well, I personally would use another character as a delimiter like '#' since the $ char is a regexp special char which matches at the end of the string the regex pattern is applied to. That said the few times I had to work on windows servers I found that every regular expressions has to be passed through preg_quote function, nevermind if it contains or not regexp special chars.
$request=preg_replace('#(^'.preg_quote($webRoot).')#i','',$requestUri);
abidibo's answer is correct, but apparently the problem was caused by a bug in str_replace() function. For some reason, in Windows Apache and nginx, this function corrupts the string and pads it with symbols that cannot be read.

replicate preg replace with javascript

Is it possible to replicate this with javascript?
preg_replace('/(.gif|.jpg|.png)/', '_thumb$1', $f['logo']);
EDIT - I am not getting this following error for this peice of code,
unterminated string literal
$('#feed').prepend('<div class="feed-item"><img src="'+html.logo.replace(/(.gif|.jpg|.png)/g, "_thumb$1")+'"/>
<div class="content">'+html.content+'</div></div>').fadeIn('slow');
There are a couple of problems with the code you are trying to replicate:
It matches "extensions" even if they aren't at the end of the filename.
The dot in a regular expression matches (nearly*) any character, not just a period.
Try this instead:
'abc.jpg'.replace(/\.(jpg|gif|png)$/, '_thumbs$&')
I'm assuming that the string you are trying to replace contains only a single filename.
*See the documentation for PCRE_DOTALL.
Yes, except that in JavaScript, replace is a string's method, so it would be rearranged a little (also, the array/object notation is slightly different):
f.logo.replace(/\.(gif|jpg|png)/, '_thumb.$1');
more info
somestringvar.replace(/(.gif|.jpg|.png)/, replacementValue)

Categories