Search and replace number in string with PHP preg_replace - php

I've got this format: 00-0000 and would like to get to 0000-0000.
My code so far:
<?php
$string = '11-2222';
echo $string . "\n";
echo preg_replace('~(\d{2})[-](\d{4})~', "$1_$2", $string) . "\n";
echo preg_replace('~(\d{2})[-](\d{4})~', "$100$2", $string) . "\n";
The problem is - the 0's won't be added properly (I guess preg_replace thinks I'm talking about argument $100 and not $1)
How can I get this working?

You could try the below.
echo preg_replace('~(?<=\d{2})-(?=\d{4})~', "00", $string) . "\n";
This will replace hyphen to 00. You still make it simple
or
preg_replace('~-(\d{2})~', "$1-", $string)

The replacement string "$100$2" is interpreted as the content of capturing group 100, followed by the content of capturing group 2.
In order to force it to use the content of capturing group 1, you can specify it as:
echo preg_replace('~(\d{2})[-](\d{4})~', '${1}00$2', $string) . "\n";
Take note how I specify the replacement string in single-quoted string. If you specify it in double-quoted string, PHP will attempt (and fail) at expanding variable named 1.

Related

php preg_replace not putting dash back in?

So, I'm doing some manipulation on lat/long pairs, and I need to turn this:
39.1889375383777,-94.48019109594397
into:
39.1889375383777 -94.48019109594397
I can't use str_replace, unless I want to have an array of 10 search and 10 replace strings, so I was hoping to use preg_replace:
$query1 = preg_replace( "/([0-9-]),([0-9-])/", "\1 \2", $query );
The problem is that the "-" gets lost:
39.1889375383777 94.48019109594397
Note, that I have a string containing a list of these, trying to do all at once:
[[39.1889375383777,-94.48019109594397],[39.18425796890108,-94.28288005131176],[39.41972019529712,-94.19956344733345],[39.41412315915102,-94.41932608390658],[39.34785744845041,-94.4893603307242],[39.1889375383777,-94.48019109594397]]
I managed to make this work with preg_replace_callback:
$str = preg_replace_callback( "/([0-9-]),([0-9-])/",
function ($matches) {return $matches[1] . " " . $matches[2];},
$query
);
But still not sure why the simpler preg_match didn't work?
Your main issue is that "\1 \2" define a "\x1\x20\x2" string, where the first character is a SOH char and the third one is STX char (see the ASCII table). To define backreferences, you need to use a literal backslash, "\\", or, better, use $n notation, and better inside a single-quoted string literal.
You can also use a solution without backreferences:
preg_replace('~(?<=\d),(?=-?\d)~', ' ', $str)
Details:
(?<=\d) - a location that is immediately preceded with a digit
, - a comma
(?=-?\d) - a location that is immediately followed with an optional - and a digit.
See the PHP demo:
$str = '[[39.1889375383777,-94.48019109594397],[39.18425796890108,-94.28288005131176],[39.41972019529712,-94.19956344733345],[39.41412315915102,-94.41932608390658],[39.34785744845041,-94.4893603307242],[39.1889375383777,-94.48019109594397]]';
echo preg_replace('~(?<=\d),(?=-?\d)~', ' ', $str);
// => [[39.1889375383777 -94.48019109594397],[39.18425796890108 -94.28288005131176],[39.41972019529712 -94.19956344733345],[39.41412315915102 -94.41932608390658],[39.34785744845041 -94.4893603307242],[39.1889375383777 -94.48019109594397]]

Capture Group Not Captured in Preg_replace Replacement

I have the following code:
$f = 'IMG_1474.PNG';
preg_replace('/(.*)([.][^.]+$)/', '$1' . time() . '$2', $f)
which should split the IMG_1474 and .PNG and add the epoch in between. The first capture group appears to be empty though.
If preg_match is used I can see the first capture group is not empty (so regex performs the same in PHP as on regex101).
preg_match('/(.*)([.][^.]+$)/', $f, $match);
print_r($match);
Functional demo: https://3v4l.org/VgDWJ (the 604147502 is the time() result)
My presumption is that something is happening with the concatenation on the replace bit.
In fact, the issue is the concatenation of the capture groups with time(). Use this version instead:
$f = 'IMG_1474.PNG';
$output = preg_replace('/(.*)([.][^.]+$)/', '${1}' . time() . '${2}', $f);
echo $output;
This prints:
IMG_14741604148316.PNG
^^^^^^^^^^ second since epoch (1970-01-01)
To understand why this is happening, we have to consider that variable substitution occurs before the preg_replace function call does. So your concatenated replacement term:
'$1' . time() . '$2'
actually first becomes:
'$1' . '1604148623' . '$2'
which is:
'$11604148623' . '$2'
The "first" capture group here is probably being interpreted as $11 (or $116, etc.), and is not defined. This is why you are currently only getting the second capture group, but the first one is empty. The solution I suggested uses ${1} which preserves the capture group reference so it is available during the preg_replace call as you intend.

how to remove duplicated character in string using php?

I'am doing a project which is cleaning text with php.
say that i have string like this :
$string = 'Life is like. . . . . . a box of chocolate. . . . . '; //each dot separated by space
How can i get the output like
$string ='Life is like a box of chocolate';
You can use preg_replace
$string = 'Life is like. . . . . . a box of chocolate. . . . . ';
echo preg_replace('/[.,]/', '', $string);
If your expected result is just to strip the dots and surrounding spaces, you can use preg_replace, but to get your expected result you need a bit more complex regex:
echo preg_replace(array("/(?<!\w) *\. */", "/(?<=\w)\. */"), array("", " "), $string);
Here I use an array of two regex to match two different cases:
a dot followed and preceded by 0 or more spaces, all preceded by a character which is not a letter or a digit (\w in regex means a letter or a digit, and this is a negative lookbehind). This is substituted by an empty string.
a dot followed by 0 or more spaces, and preceded by a letter or a digit. This is substituted by a space.
2 is to match and remove the dot in 'like. ' but leave a single space after the word.
This gives your expected result: 'Life is like a box of chocolate'
You can learn more on regex (short for regular expression) looking for tutorials on the web.
isn't it an easy str_replace()?
str_replace(". ", "", $text);

Passing Charachter in to Regex in PHP

I would like to pass characters like A,B,C,D like this to a preg_match function in PHP.
Eg >
if (preg_match ("/^SEQRES.*\s$char\s.*/", $amino)) ;
I would like to pass A,B,C,D to $char and loop through the match.
please give me a solution.
Just use string concatenation:
$re = "/^SEQRES.*\s" . $char . "\s.*/";
if (preg_match($re, $amino))
....
There is no need for a loop. Simply replace $char with "[A-D]";. Since you have bounded it by spaces, it will match one single character in the class [A-D] between spaces .
if (preg_match ("/^SEQRES.*\s[A-D]\s.*/", $amino)) ;
You may also wish to use preg_match_all().
Use preg_quote if you are getting the character from user input:
$re = "/^SEQRES.*\s" . preg_quote($char) . "\s.*/";

How to append or replace trailing question marks using preg_replace?

I want to enforce single question mark at the and of the string. In JavaScript it works perfectly:
var re = /[?7!1]*$/;
document.write('lolwut'.replace(re, '?'));
document.write('lolwut?'.replace(re, '?'));
document.write('lolwut??'.replace(re, '?'));
document.write('lolwut???'.replace(re, '?'));
document.write('lolwut???!!!11'.replace(re, '?'));
All of returned values equals "lolwut?"
PHP variant doesnt work that smooth:
$re = '/[?7!1]*$/';
echo preg_replace($re, '?', 'lolwut') . "\n";
echo preg_replace($re, '?', 'lolwut?') . "\n";
echo preg_replace($re, '?', 'lolwut??') . "\n";
echo preg_replace($re, '?', 'lolwut???') . "\n";
echo preg_replace($re, '?', 'lolwut???!!!11') . "\n";
output is:
lolwut?
lolwut??
lolwut??
lolwut??
lolwut??
What i'm doing wrong here?
Update:
$ (Dollar) Assert end of string
An assertion is a test on the characters following or preceding the current matching point that does not actually consume any characters.
is my confusion here, along with implicit global flag of preg_replace, thanks to salathe for providing a clue. (you guys should vote his answer up, really)
Checkout rtrim() - http://php.net/manual/en/function.rtrim.php
echo rtrim('lolwut','?7!1').'?'; // lolwut?
echo rtrim('lolwut?','?7!1').'?'; // lolwut?
echo rtrim('lolwut??','?7!1').'?'; // lolwut?
echo rtrim('lolwut???!!!11','?7!1').'?'; // lolwut?
echo rtrim('lolwut1??!7!11','?7!1').'?'; // lolwut?
rtrim will Strip whitespace (or other characters) from the end of a string
The second argument:
You can also specify the characters you want to strip, by means of the charlist parameter. Simply list all characters that you want to be stripped. With .. you can specify a range of characters.
Just to answer the question asked ("What i'm doing wrong here?"), you're being confused about what precisely the regular expression matches. With the strings presented, bar the first one, the regex actually matches twice which is why you get two question marks (two matches, two replacements). The root of this behaviour is a mixture of the quantifier (* allows matching nothing) and the end-anchor ($ matches the end of the string).
For lolwut???!!!11:
The regex first matches ???!!!11 which is what you expect
Giving the string a new value of lulwut?
Then it also matches at the point right at the end of the new string
Leading to a final replaced value of lulwut??
If you wanted to continue using the same regex with preg_replace then simply restrict it to one replacement by providing a value of 1 to the fourth ($limit) argument:
preg_replace('/[?7!1]*$/', '?', 'lolwut???!!!111', 1);
// limit to only one replacement ------------------^
As for a better solution, as the others have said, use rtrim.
You should use the trim function:
echo trim('lolwut???!!!11', '?7!1');
output is:
lolwut

Categories