2

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 .*.

5
  • Looks like an XY problem. Why are you mutilating this text? Commented Nov 13, 2020 at 10:21
  • @mickmackusa what do you mean by mutilating? I have an app and I need to give access to it by some guid. App sends its guid to php script I mentioned, and if the guid(rule) exist, the server will respond 1, if no - 0. I need a script that will add/change/delete rules, that what I am asking about here Commented Nov 13, 2020 at 10:26
  • My thinking is that if you are modifying the contents of a php file like this, there is sure to be a cleaner and more reliable way to adjust rules. The title of this question lacks specificity. According to PSR-12 standards, else if should be elseif and curly braces should be used. Commented Nov 13, 2020 at 11:50
  • @mickmackusa yes, this is an php file, but, I have already done my work, with else if, without braces, and all works perfectly Commented Nov 14, 2020 at 10:20
  • I don't question that it works. I am just saying that it is not aligning with the recommended coding standard. @Oku Commented Nov 14, 2020 at 10:26

2 Answers 2

1

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.

  1. \Q...\E means "treat everything in between these two metacharacters literally"
  2. 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.
  3. The second occurrence of $rule in the pattern DOES need to be interpreted as the variable so it is not escaped.
  4. The \R is a metacharacter which means \n, \r and \r\n
  5. Finally match all of the next line with the "any character" . with a one or more quantifier (+).
Sign up to request clarification or add additional context in comments.

2 Comments

The only problem in Your and @TheFourthBird answer is that it lefts an empty line after replacement and it is not pretty. So I add a \R metacharacter to the end. It always works because (I should mentioned it) in the end, there always is else echo 0; block, so newline after else if will always exist. Thanks.
Excellent. The extra trailing \R would have been my advice.
0

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

4 Comments

Thanks for feedback, but I didn’t understand about \\n, why then it works in case of $str = preg_replace("/$rule'\)\necho '{\"s\":[0-9]/", $rule."')\necho '{\"s\":1", $str);?
@Okumaima You are right, it can just be \n. I have updated it.
But $ still should be double quoted?
@Okumaima Yes because else $ by itself would assert the end of the string.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.