Regex "1 Month, -$7.50" to replace "-$7.50" with "-10%" - php

This is my attempt, but it's not working. I'm so rusty at regex these days so I have no idea what's wrong with it. Any help?
$pattern = '/-\$[.*]$/';

You need to put the * outside of the [] (or better yet, use a +).
Try '/-\$[0-9\.]+/':
$pattern = '/-\$[0-9\.]+/';
Or, if -$7.50 will always be at the end of the line:
$pattern = '/-\$[0-9\.]+$/';

$pattern = '/-\$(.*)$/';
If I understood well. The number will be accessible as "$1" in the replace string

Try with:
$pattern = '/-\$\d+\.\d+/';
It will match minus sign (if you change it into -?, minus will be optional), digits, dot and digits after dot.

<?php
$string = 'Wow! -$7.50 now!';
$pattern = '/-\$(\d+)\.(\d+)/';
$replacement = '-10%';
echo preg_replace($pattern, $replacement, $string);
?>

Related

preg_replace issue. Character class inside other character class

I have a fragment in text like
;flat
CID_999999 = 99999999
CID_999999 = 99999999
CID_999999 = 99999999
CID_999999 = 99999999
where 999999 are some numbers. I want to find this fragment by regexp.
When I use this regex:
preg_replace('/;flat[\s\r\n]+[CID_0-9]+\s=\s[0-9]+\n/','REPLACEMENT',$content);
it replaces ;flat and first CID string.
So, I suppose that if I put [CID_0-9]+\s=\s[0-9]+\n part in character class []+it will remove all CID strings. But if I do it it doesn't replace anything. So I don't understand something in regex. What am I doing wrong?
I thought that expected output is clear, but ok. I should replace all fragment by REPLACEMENT.
Use lookbehind if you are trying to match just the digits after the = and before the newline
For more accurate matching use CID[0-9]+ rather than [CID0-9]+
preg_replace('/(?<;flat[\s\r\n]+CID_[0-9]+\s=\s)[0-9]+(?=\n)/','REPLACEMENT',$content);
You don't need a character class ([...]); you need a group ((...)). Your code should look like this:
preg_replace('/;flat[\s\r\n]+([CID_0-9]+\s=\s[0-9]+\n?)+/', 'REPLACEMENT', $content);
Note the ? at the end, just in case your last line isn't terminated with a new line (\n) character.
Demo
;flat\s*|(?!^)\G(CID_\d+\s*=\s*\d+\s*)
Try this.Replace by $1.See demo.
https://regex101.com/r/gQ3kS4/7
$re = "/;flat\\s*|(?!^)\\G(CID_\\d+\\s*=\\s*\\d+\\s*)/";
$str = ";flat\nCID_999999 = 99999999\nCID_999999 = 99999999\nCID_999999 = 99999999\nCID_999999 = 99999999\n;";
$subst = "$1";
$result = preg_replace($re, $subst, $str);

Regular Expression to replace a bracket with word in front when not preceded by word

I am facing problem with a regular expression.
I have a string like ('A'&'B')
Now I want to convert it to CONCAT('A'&'B') which is simple and I have done using
str_replace("(", "CONCAT(", $subject)
But I want to replace "(" to "CONCAT(" if the string doesn't have prior string "extract_json_value".
So I don't want to replace extract_json_value('A'&'B') to extract_json_valueCONCAT('A'&'B') but it will stay as it is extract_json_value('A'&'B').
You can expand your regex with a negative lookbehind:
(?<!extract_json_value)\(
Here is a regex demo!
You could use strpos to do this.
if (strpos($subject, '(') === 0) {
$subject = str_replace('(', 'CONCAT(', $subject);
}
If your string contains other text you can use preg_replace() and use a word boundary \B for this.
$subject = preg_replace('/\B\(/', 'CONCAT(', $subject);
You can use negative lookbehind in order to match a group not preceded by a string.
First, let's have a regexp matching all strings but those containing "extract_json_value":
(?<!extract_json_value).*
Now, let's use preg_replace
$string = "extract_json_value('A'&'B')";
$pattern = '/^(?<!extract_json_value)(\(.+\))$/';
$replacement = 'CONCAT\1';
echo preg_replace($pattern, $replacement, $string);
// prints out "extract_json_value('A'&'B')"
It works too with
$string = "('A'&'B')";
...
// prints out "CONCAT('A'&'B')"
However, it does not work with
$string = "hello('A'&'B')";
...
// prints out "helloCONCAT('A'&'B')"
So, continue with a preg_replace_callback:
http://php.net/manual/fr/function.preg-replace-callback.php

preg_replace only substring before defined char

I'm trying to replace chars not [A-Z] and before the # inside a string. So this
AreplacehereZ#domain.tld
needs to become:
A***********Z#domain.tld
I tried with:
$string = 'AreplacehereZ#domain.tld';
$pattern = '/(?<!#)[^A-Z#\.]/';
$replacement = '*';
$replace = preg_replace($pattern, $replacement, $tring);
but the result is
'A***********Z#d*****.***'
So I can't find the way how to avoid the replacement of #domain.tld by only using preg_replace().
domain.tld can be anything so I can't use (?<!#domain.tld) in the $pattern var.
You can just assert that from the current position, match [^A-Z], then make sure you can consume any number of characters but still hit the #:
$pattern = '/[^A-Z](?=[^#]*#)/';
Produces:
A***********Z#domain.tld

How to extract a collection of numbers from a string?

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

Some confusion with preg_replace

I am very confused with preg_replace, I have this string and I would like to change ONLY the number before the _
$string = 'string/1_491107.jpg';
$newstring = preg_replace('#([0-9]+)_#', '666', $string);
But then I get "string/666491107.jpg" instead "string/666_491107.jpg"
Thanks
What you're doing here is matching the numbers in the parenthesis as $1 in your replacement. You don't actually say "only the stuff in parenthesises should be replaced".
You could do it like this:
$string = 'string/1_491107.jpg';
$newstring = preg_replace('#[0-9]+_#', '666_', $string);
or you could use a positive lookahead (only match a number sequence followed by an underscore, but don't include the underscore in the match):
$string = 'string/1_491107.jpg';
$newstring = preg_replace('#[0-9]+(?=_)#', '666', $string);
Regex 101 demo
You've got the underscore as part of the text to be replaced; so you also need to include it in the replacement:
$string = 'string/1_491107.jpg';
$newstring = preg_replace('#([0-9]+)_#', '666_', $string);

Categories