Regex only grabbing first digit - php

I'm trying to grab everything after the following digits, so I end up with just the store name in this string:
full string: /stores/1077029-gacha-pins
what I want to ignore: /stores/1077029-
what I need to grab: gacha-pins
Those digits can change at any time so it's not specifically that ID, but any numbers after /stores/
My attempt so far is only grabbing /stores/1
\/stores\/[0-9]
I'm still trying, just thought I would see if I can get some help in the meantime too, will post an answer if I solve.

You may use
'~/stores/\d+-\K[^/]+$~'
Or a more specific one:
'~/stores/\d+-\K\w+(?:-\w+)*$~'
See the regex demo and this regex demo.
Details
/stores/ - a literal string
\d+ - 1+ digits
- - a hyphen
\K - match reset operator
[^/]+ - any 1+ chars other than /
\w+(?:-\w+)* - 1+ word chars and then 0+ sequences of - and 1+ word chars
$ - end of string.
See the PHP demo:
$s = "/stores/1077029-gacha-pins";
$rx = '~/stores/\d+-\K[^/]+$~';
if (preg_match($rx, $s, $matches)) {
echo "Result: " . $matches[0];
}
// => Result: gacha-pins

You should do it like this:
$string = '/stores/1077029-gacha-pins';
preg_match('#/stores/[0-9-]+(.*)#', $string, $matches);
$part = $matches[1];
print_r($part);

Related

Getting zipcode from a string

I am trying to get zipcodes out of address strings.
Zipcodes may look like this: 23-123 or 50-530.
Strings usually look like this: Street 50, 50-123 City
What I tried to do is finding the position of the zipcode and cut the next 6 characters starting from that point. Unfortunatelly strpos returns false all the time.
$zipCodePosition = strpos($form->address, "\d{2}-\d{3}");
$zipCode = $zipCodePosition ? substr($form->address, $zipCodePosition , 6) : '';
The strpos does not allow the use of regex as an argument.
You need a preg_match / preg_match_all here:
// Get the first match
if (preg_match('~\b\d{2}-\d{3}\b~', $text, $match)) {
echo $match[0];
}
// Get all matches
if (preg_match_all('~\b\d{2}-\d{3}\b~', $text, $matches)) {
print_r($matches[0]);
}
The regex matches
\b - a word boundary
\d{2} - two digits
- - a hyphen
\d{3} - three digits
\b - a word boundary
See the regex demo.

Looking for regex to obfuscate email to t*#w***.de

I have the following:
$pattern = "/^([\w_]{1})(.+)([\w_]{1}#)/u";
$replacement = "$1*$3***$4";
$email = "testa#weste.de";
echo "obfuscated: ".preg_replace($pattern, $replacement, $email).RT;
The result is: t*a#***weste.de
But I would like to have: t*#w***.de
How to grab the letter after the # and not before. And how does it work with the .de part?
For the replacement in the example data, you might use a match with \K to forget what is matched after the first character and keep it.
To keep the first character after the # sign, you can use a capture group and use that in the replacement.
^\w\K[^\s#]+#(\w)[^\s.#]+
^ Start of string
\w Match a single word char (That will also match _)
\K Forget what is matched so far
[^\s#]+ Match 1+ chars other than # or a whitespace char
# Match the # char
(\w) Capture group 1, match a word char (to keep)
[^\s.#]+ Match 1+ chars other than #, a whitespace char or dot
Regex demo | Php demo
In the replacement use a single capture group *#$1***
$email = "testa#weste.de";
$pattern = "/^\w\K[^\s#]+#(\w)[^\s.#]+/";
$replacement = "*#$1***";
echo preg_replace($pattern, $replacement, $email);
Output
t*#w***.de
You can make the pattern as specific as you would like. If there should for example be a dot followed by at least 2 chars a-z at the end of the string, and you don't want to stop matching at the first dot after the #
^\w\K[^\s#]+#(\w)[^\s#]+(?=\.[a-z]{2,}$)
Regex demo
I found this way to do it:
$email = 'someemail#domain.com'
[$firstPart, $lastPart] = explode('#', $email);
$maskedEmail = str_replace(substr($firstPart, 0, 7), str_repeat('*', 7), $email);
Uses PHP native functions and works just fine!

Replace 3d whitespace with comma and whitespace in string

To replace a whitespace with a comma and whitespace in a string I should do something like this:
$result = preg_replace('/[ ]+/', ', ', trim($value));
The result: Some, example, here, for, you
However, I only want to replace the 3d white space, so that the result would look like this:
Some example here, for you
How do I do that?
You may use something like
$value = " Some example here for you ";
$result = preg_replace('/^\S+(?:\s+\S+){2}\K\s+/', ',$0', trim($value), 1);
echo $result; // => Some example here, for you
See the PHP demo and the regex demo.
Pattern details
^ - start of string
\S+ - 1+ non-whitespaces
(?:\s+\S+){2} - two consecutive occurrences of
\s+ - 1+ whitespaces
\S+ - 1+ non-whitespaces
\K - a match reset operator
\s+ - (the $0 in the replacement pattern references this substring) 1+ whitespaces.
You can use an callback function and control when to replace:
<?php
$string = 'Some example here for you';
$i = 0;
$string = preg_replace_callback('/\s+/',function($m) use(&$i){
$i++;
if($i == 3) {
return ', ';
}
return ' ';
},$string);
echo $string;
Try this
$result = preg_replace('/^([^\s]+)\s+((?1)\s+(?1))/', '\1 \2,', trim($value));
Test it
Explanation:
^ start of string
([^\s]+) - capture everything not a space
\s+ space 1 or more
((?1)\s+(?1)) - (?1) repeat first capture group, we do this 2x with a space between, and capture that. I guess you could capture them separately, but what's the point.
The nice thing about (?{n}) is if you have to change the regex for the word capturing you only have to change it 1 time, not 3. Probably it doesn't matter here so much, but I like using it...

How to export number of days from string "x days"

How can I export the 4 from string:
9 buy property stocks over 4 days
I can export the numbers by doing:
$numbers = preg_replace('/[^0-9]+/', '', $string);
but I just want the number that is followed by days?
You may use a a matching regex with preg_match:
if (preg_match('/\d+(?=\s*days)/', $string, $m)) {
echo $m[0];
}
See the PHP demo and a regex demo. The \d+(?=\s*days) pattern matches 1+ digits (\d+) that are followed with 0+ whitespaces (\s*) and a substring days.
The same regex with a capturing group will look like
if (preg_match('/(\d+)\s*days/', $string, $m)) {
echo $m[1];
}
See another PHP demo and another regex demo. Here, the 1+ digits are captured into a group and can be accessed via $m[1].
You can use:
$days = preg_replace('/.*(\d+) days/i', '\1', $string);
Regex Demo
PHP Demo

split string in numbers and text but accept text with a single digit inside

Let's say I want to split this string in two variables:
$string = "levis 501";
I will use
preg_match('/\d+/', $string, $num);
preg_match('/\D+/', $string, $text);
but then let's say I want to split this one in two
$string = "levis 5° 501";
as $text = "levis 5°"; and $num = "501";
So my guess is I should add a rule to the preg_match('/\d+/', $string, $num); that looks for numbers only at the END of the string and I want it to be between 2 and 3 digits.
But also the $text match now has one number inside...
How would you do it?
To slit a string in two parts, use any of the following:
preg_match('~^(.*?)\s*(\d+)\D*$~s', $s, $matches);
This regex matches:
^ - the start of the string
(.*?) - Group 1 capturing any one or more characters, as few as possible (as *? is a "lazy" quantifier) up to...
\s* - zero or more whitespace symbols
(\d+) - Group 2 capturing 1 or more digits
\D* - zero or more characters other than digit (it is the opposite shorthand character class to \d)
$ - end of string.
The ~s modifier is a DOTALL one forcing the . to match any character, even a newline, that it does not match without this modifier.
Or
preg_split('~\s*(?=\s*\d+\D*$)~', $s);
This \s*(?=\s*\d+\D*$) pattern:
\s* - zero or more whitespaces, but only if followed by...
(?=\s*\d+\D*$) - zero or more whitespaces followed with 1+ digits followed with 0+ characters other than digits followed with end of string.
The (?=...) construct is a positive lookahead that does not consume characters and just checks if the pattern inside matches and if yes, returns "true", and if not, no match occurs.
See IDEONE demo:
$s = "levis 5° 501";
preg_match('~^(.*?)\s*(\d+)\D*$~s', $s, $matches);
print_r($matches[1] . ": ". $matches[2]. PHP_EOL);
print_r(preg_split('~\s*(?=\s*\d+\D*$)~', $s, 2));

Categories