Regex to replace non escaped Quotes - php

After having some trouble building a json string I discovered some text in my database containing double quotes. I need to replace the quotes with their escaped equivalents. This works:
function escape( $str ) {
return preg_replace('/"/',"\\\"",$str);
}
but it doesn't take into account that a quote may already be escaped. How can I modify the expression so that it's only true only for a non escaped character?

You need to use a negative lookbehind here
function escape( $str ) {
return preg_replace('/(?<!\\)"/',"\\\"",$str);
}

Try first remove the '\' from all escaped doube-quotes, than escape all double-quotes.
str_replace(array('\"', '"'), array('"', '\"'), $str);

Try preg_replace('/([^\\\])"/', '$1\\"', $str);

I believe this will work
regex:
(?<!\\)((?:\\\\)*)"
code:
$re = '/(?<!\\\\)((?:\\\\\\\\)*)"/';
preg_replace($re, '$1\\"', 'foo"bar'); // foo\"bar -- slash added
preg_replace($re, '$1\\"', 'foo\\"bar'); // foo\"bar -- already escaped, nothing added
preg_replace($re, '$1\\"', 'foo\\\\"bar'); // foo\\\"bar -- not escaped, extra slash added

Related

Dynamically replace part of a condition block with regex

There is a string in format:
else if($rule=='somerule1')
echo '{"s":1,"n":"name surname"}';
else if($rule=='somerule2')
echo '{"s":1,"n":"another text here"}';
...
"s" can have only number, "n" any text.
In input I have $rule value, and I need to remove the else if block that corresponds to this value. I am trying this:
$str = preg_replace("/else if\(\$rule=='$rule'\)\necho '{\"s\":[0-9],\"n\":\".*\"/", "", $str);
where $str is a string, that contains blocks I mentioned above, $rule is a string with rule I need to remove. But the function returns $str without changes.
What do I do wrong?
For example, script to change "s" value to 1 works nice:
$str = preg_replace("/$rule'\)\necho '{\"s\":[0-9]/", $rule."')\necho '{\"s\":1", $str);
So, probably, I am doing mistake with = symbol, or maybe with space, or with .*.
The regex pattern can be much less strict, much simpler, and far easier to read/maintain.
You need to literally match the first line (conditional expression) with the only dynamic component being the $rule variable, then match the entire line that immediately follows it.
Code: (Demo)
$contents = <<<'TEXT'
else if($rule=='somerule1')
echo '{"s":1,"n":"name surname"}';
else if($rule=='somerule2')
echo '{"s":1,"n":"another text here"}';
TEXT;
$rule = "somerule1";
echo preg_replace("~\Qelse if(\$rule=='$rule')\E\R.+~", "", $contents);
Output:
else if($rule=='somerule2')
echo '{"s":1,"n":"another text here"}';
So, what have I done? Here's the official pattern demo.
\Q...\E means "treat everything in between these two metacharacters literally"
Then the only character that needs escaping is the first $, this is not to stop it from being interpreted as a end-of-string metacharacter, but as the start of the $rule variable because the pattern is wrapped in double quotes.
The second occurrence of $rule in the pattern DOES need to be interpreted as the variable so it is not escaped.
The \R is a metacharacter which means \n, \r and \r\n
Finally match all of the next line with the "any character" . with a one or more quantifier (+).
The pattern does not match because you have to use a double escape to match the backslash \\\$.
Apart from that, you are not matching the whole line as this part ".*\" stops at the double quote before }';
$str = 'else if($rule==\'somerule1\')
echo \'{"s":1,"n":"name surname"}\';
else if($rule==\'somerule2\')
echo \'{"s":1,"n":"another text here"}\';';
$rule = "somerule1";
$pattern = "/else if\(\\\$rule=='$rule'\)\necho '{\"s\":\d+,\"n\":\"[^\"]*\"}';/";
$str = preg_replace($pattern, "", $str);
echo $str;
Output
else if($rule=='somerule2')
echo '{"s":1,"n":"another text here"}';
Php demo

Remove backwards slashes in string

When running a function which returns a string, I end up with backwards-slashes before a quotation marks, like this:
$string = get_string();
// returns: Example
I suspect it is some type of escaping happening somewhere. I know I can string replace the backwards-slash, but I suppose in these cases, there is some type of unescape function you run?
You only need to escape quotes when it matches your starting/ending delimiter. This code should work properly:
$string = 'Example';
If your string is enclosed in single quotes ', then " doesn't need to be escaped. Likewise, the opposite is true.
Avoid using stripslashes(), as it could cause issues if single quotes need to contain slashes. A simple find/replace should work for you:
$string = 'Example';
$string = str_replace($string, '\"', '"');
echo $string; //echos Example
<?php
$string = 'Example';
echo stripslashes($string);
?>

simple preg_replace() not working right for me :/

$str = "{Controller}/{Action}";
$str = preg_replace("/\//","\\/",$str);
$str = preg_replace("/(\{\w+\})\\/(\{\w+\})/","\\1 slash \\2",$str);
echo $str;
So the third line doesn't do anything for me, could anyone say where i was wrong? It works if i put something else instead of \/
thanks in advance;)
This will work:
$str = "{Controller}/{Action}";
$str = preg_replace('#(\{\w+\})/(\{\w+\})#', '\1 slash \2', $str);
echo $str;
Output: {Controller} slash {Action}
Remarks:
You should use single quotes to reduce the need for escaping and therefore much better readability.
You also should consider using another delimiter if you are matching literal slashes (eg #, but anything works)

Replace all quote marks but leave escaped characters

I'm trying to remove all quote characters from a string but not those that are escaped.
Example:
#TEST string "quoted part\" which escapes" other "quoted string"
Should result in:
#TEST string quoted part\" which escapes other quoted string
I tried to achieve this using
$string = '#TEST string "quoted part\" which escapes" other "quoted string"'
preg_replace("/(?>=\\)([\"])/","", $string);
But can't seem to find a match pattern.
Any help or tip on an other approach
A very good example for (*SKIP)(*FAIL):
\\['"](*SKIP)(*FAIL)|["']
Replace this with an empty string and you're fine. See a demo on regex101.com.
In PHP this would be (you need to escape the backslash as well):
<?php
$string = <<<DATA
#TEST string "quoted part\" witch escape" other "quoted string"
DATA;
$regex = '~\\\\[\'"](*SKIP)(*FAIL)|["\']~';
$string = preg_replace($regex, '', $string);
echo $string;
?>
See a demo on ideone.com.
While (*SKIP)(*F) is a good technique all in all, it seems you may use a mere negative lookbehind in this case, where no other escape entities may appear but escaped quotes:
preg_replace("/(?<!\\\\)[\"']/","", $string);
See the regex demo.
Here, the regex matches...
(?<!\\\\) - a position inside the string that is not immediately preceded with a literal backslash (note that in PHP string literals, you need two backslashes to define a literal backslash, and to match a literal backslash with a regex pattern, the literal backslash in the string literal must be doubled since the backslash is a special regex metacharacter)
[\"'] - a double or single quote.
PHP demo:
$str = '#TEST string "quoted part\\" witch escape" other "quoted string"';
$res = preg_replace('/(?<!\\\\)[\'"]/', '', $str);
echo $res;
// => #TEST string quoted part\" witch escape other quoted string
In case backslashes may also be escaped in the input, you need to make sure you do not match a " that comes after two \\ (since in that case, a " is not escaped):
preg_replace("/(?<!\\\\)((?:\\\\{2})*)[\"']/",'$1', $string);
The ((?:\\\\{2})*) part will capture paired \s before " or ' and will put them back with the help of the $1 backreference.
May be this
$str = '#TEST string "quoted part\" witch escape" other "quoted string"';
echo preg_replace("#([^\\\])\"#", "$1", $str);

PHP rtrim all trailing special characters

I'm making a function that that detect and remove all trailing special characters from string. It can convert strings like :
"hello-world"
"hello-world/"
"hello-world--"
"hello-world/%--+..."
into "hello-world".
anyone knows the trick without writing a lot of codes?
Just for fun
[^a-z\s]+
Regex demo
Explanation:
[^x]: One character that is not x sample
\s: "whitespace character": space, tab, newline, carriage return, vertical tab sample
+: One or more sample
PHP:
$re = "/[^a-z\\s]+/i";
$str = "Hello world\nhello world/\nhello world--\nhellow world/%--+...";
$subst = "";
$result = preg_replace($re, $subst, $str);
try this
$string = preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
or escape apostraphe from string
preg_replace('/[^A-Za-z0-9\-\']/', '', $string); // escape apostraphe
You could use a regex like this, depending on your definition of "special characters":
function clean_string($input) {
return preg_replace('/\W+$/', '', $input);
}
It replaces any characters that are not a word character (\W) at the end of the string $ with nothing. \W will match [^a-zA-Z0-9_], so anything that is not a letter, digit, or underscore will get replaced. To specify which characters are special chars, use a regex like this, where you put all your special chars within the [] brackets:
function clean_string($input) {
return preg_replace('/[\/%.+-]+$/', '', $input);
}
This one is what you are looking for. :
([^\n\w\d \"]*)$
It removes anything that is not from the alphabet, a number, a space and a new line.
Just call it like this :
preg_replace('/([^\n\w\s]*)$/', '', $string);

Categories