$string = "Hot_Chicks_call_me_at_123456789";
How can I strip away so that I only have the numberst after the last letter in the string above?
Example, I need a way to check a string and remove everything in front of (the last UNDERSCORE FOLLOWED by the NUMBERS)
Any smart solutions for this?
Thanks
BTW, it's PHP!
Without using a regular expression
$string = "Hot_Chicks_call_me_at_123456789";
echo end( explode( '_', $string ) );
If it always ends in a number you can just match /(\d+)$/ with regex, is the formatting consistent? Is there anything between the numbers like dashes or spaces?
You can use preg_match for the regex part.
<?php
$subject = "abcdef_sdlfjk_kjdf_39843489328";
preg_match('/(\d+)$/', $subject, $matches);
if ( count( $matches ) > 1 ) {
echo $matches[1];
}
I only recommend this solution if speed isn't an issue, and if the formatting is completely consistent.
PHP's PCRE Regular Expression engine was built for this kind of task
$string = "Hot_Chicks_call_me_at_123456789";
$new_string = preg_replace('{^.*_(\d+)$}x','$1',$string);
//same thing, but with whitespace ignoring and comments turned on for explanations
$new_string = preg_replace('{
^.* #match any character at start of string
_ #up to the last underscore
(\d+) #followed by all digits repeating at least once
$ #up to the end of the string
}x','$1',$string);
echo $new_string . "\n";
To be a bit churlish, your stated specification would suggest the following algorithm:
def trailing_number(s):
results = list()
for char in reversed(s):
if char.isalpha(): break
if char.isdigit(): results.append(char)
return ''.join(reversed(results))
It returns only the digits from the end of the string up to the first letter it encounters.
Of course this example is in Python, since I don't know PHP nearly as well. However it should be easily translated as the concept is easy enough ... reverse the string (or iterate from the end towards the beginning) and accumulate digits until you find a letter and break (or fall out of the loop at the beginning of the string).
In C it would be more efficient to use something a bit like for(x=strlen(s);x>s;x--) to walk backwards through the string, saving a pointer to the most recently encountered digit until we break or drop out of the loop at the beginning of the string. Then return the pointer into the middle of the string where our most recent (leftmost) digit was found.
Related
I've got strings like the following:
Hi X
Blah
Kind regards
ABC
And
Hi X
Blah
Regards
CBA
So the key is the newline and the word "regards" (case insensitive). I'd like to use PHP to get the part of the string before the line that contains "regards". E.g. for these examples, the result should just be:
Hi X
Blah
I've tried the below but it doesn't work as intended in some cases (E.g. if "Kind" appears multiple times in the string). Thanks in advance!
$matches = array();
if (preg_match("/\n(.*?)regards/i", $message, $matches) == 1) {
$stop_at = $matches[1];
$split = explode($stop_at,$message);
$message = $split[0];
}
What you're really after is a regex that handles multi-line strings. For this, you can use the m flag (PCRE_MULTILINE).
I would use preg_split() to split the string on your token, for example
$found = trim(preg_split('/^.*regards$/im', $message, 2)[0]);
Demo ~ https://3v4l.org/idMcP
Some notes:
I've used trim() to remove the empty line after "Blah" (your examples exclude it)
I've set a limit of 2 on preg_split(). This is redundant given you're only retrieving the first split but in my head, it means PHP does less work (realities may vary).
This might fail if a line ends in a word ending in "regards" but not necessarily the word "regards", for example this word I just made up "goregards" (it's like a shin guard but for viscera).
You can use the regular expression
(?si).+\b(?=\n+[\w ]*regards)
It will match everything up to a word boundary, then lookahead for newline(s) followed by a line which has regards on it (possibly preceeded by a combination of word characters or spaces).
$str = "Hi X
Blah
Kind regards
ABC";
preg_match('/(?si).+\b(?=\n\s*[\w ]*regards)/', $str, $match);
I am testing RegExp with online regexr.com tool. I will test string with multiple cases, but I can't get substitution to work.
RexEx for matching string is:
/^[0-9]{1,3}[0-9]{6,7}$/
Which matches local mobile number in my country like this:
0921234567
But then I want to substitute number in this way: add "+" sign, add my country code "123", add "." sign, and then finaly, add matched number with stripped leading zero.
Final number will be:
+385.921234567
I have basic idea to insert matched string, but I am not sure how prepend characters, and strip zero from matched string in following substitution pattern:
\+$&\n\t
I will use PHP preg_replace function.
EDIT:
As someone mentioned wisely, there is posibility that there will be one, two or none of zeros, but I will create separate test cases with regex just testing number of zeroes. Doing so in one regex seems to complicated for now.
Possible numbers will be:
0921234567
00111921234567
Where 111 is country code. I know that some country codes consist of 2 or 3 digits, but I will create special cases, for most country codes.
You can use this preg_replace to strip optional zeroes from start of your mobile #:
$str = preg_replace('~^0*(\d{7,9})$~', '+385.$1', $str);
^[0-9]([0-9]{1,2}[0-9]{6,7})$
You just need to add groups.Replace by +385.$1.See demo.
https://regex101.com/r/cJ6zQ3/22
$re = "/^[0-9]([0-9]{1,2}[0-9]{6,7})$/m";
$str = "0921234567\n";
$subst = "+385.$1";
$result = preg_replace($re, $subst, $str);
I would use a 2-step solution:
Check if we match the main regex
Replace the number by pre-pending + + country code + . + number without leading zeros.
PHP code:
$re = "/^[0-9]{7,10}$/";
$str = "0921234567";
if (preg_match($re, $str, $match)) {
echo "+385." . preg_replace('/^0+/', '', $match[0]);
}
Note that splitting out character class in your regex pattern makes no sense when not using capture groups. ^[0-9]{7,10}$ is the same then as ^[0-9]{1,3}[0-9]{6,7}$, meaning match 7 to 10 digits from start to end of the string.
Leading zeros are easily trimmed from the start with /^0+/ regex.
really struggling with this...hopefully someone can put me on the right path to a solution.
My input string is structured like this:
66-2141-A-AC107-7
I'm interested in extracting the string 'AC107' using a single regular expression. I know how to do this with other PHP string functions, but I have to do this with a regular expression.
What I need is to extract all data between the third and fourth hyphens. The structure of each section is not fixed (i.e, 66 may be 8798709 and 2141 may be 38). The presence of the number of hyphens is guaranteed (i.e., there will always be a total of four (4) hyphens).
Any help/guidance is greatly appreciated!
This will do what you need:
(?:[^-]*-){3}([^-]+)
Debuggex Demo
Explanation:
(?:[^-]*-) Look for zero or more non-hyphen characters followed by a hyphen
{3} Look for three of the blocks just described
([^-]+) Capture all the consecutive non-hyphen characters from that point forward (will automatically cut off before the next hyphen)
You can use it in PHP like this:
$str = '66-2141-A-AC107-7';
preg_match('/^(?:[^-]*-){3}([^-]+)/', $str, $matches);
echo $matches[1]; // prints AC107
This should look for anything followed by a hyphen 3 times and then in group 2 (the second set of parenthesis) it will have your value, followed by another hyphen and anything else.
/^(.*-){3}(.*)-(.*)/
You can access it by using $2. In php, it would be like this:
$string = '66-2141-A-AC107-7';
preg_match('/^(.*-){3}(.*)-(.*)/', $string, $matches);
$special_id = $matches[2];
print $special_id;
Okay, I was hoping someone could help me with a little regex-fu.
I am trying to clean up a string.
Basically, I am:
Replacing all characters except A-Za-z0-9 with a replacement.
Replacing consecutive duplicates of the replacement with a single instance of the replacement.
Trimming the replacement from the beginning and end of the string.
Example Input:
(&&(%()$()#&#&%&%%(%$+-_The dog jumped over the log*(&)$%&)#)##%&)&^)##)
Required Output:
The+dog+jumped+over+the+log
I am currently using this very discombobulated code and just know there is a much more elegant way to accomplish this....
function clean($string, $replace){
$ok = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
$ok .= $replace;
$pattern = "/[^".preg_quote($ok, "/")."]/";
return trim(preg_replace('/'.preg_quote($replace.$replace).'+/', $replace, preg_replace($pattern, $replace, $string)),$replace);
}
Could a Regex-Fu Master please grace me with a simpler/more efficient solution?
A much better solution suggested and explained by Botond Balázs and hakre:
function clean($string, $replace, $skip=""){
// Escape $skip
$escaped = preg_quote($replace.$skip, "/");
// Regex pattern
// Replace all consecutive occurrences of "Not OK"
// characters with the replacement
$pattern = '/[^A-Za-z0-9'.$escaped.']+/';
// Execute the regex
$result = preg_replace($pattern, $replace, $string);
// Trim and return the result
return trim($result, $replace);
}
I'm not a "regex ninja" but here's how I would do it.
function clean($string, $replace){
/// Remove all "not OK" characters from the beginning and the end:
$result = preg_replace('/^[^A-Za-z0-9]+/', '', $string);
$result = preg_replace('/[^A-Za-z0-9]+$/', '', $result);
// Replace all consecutive occurrences of "not OK"
// characters with the replacement:
$result = preg_replace('/[^A-Za-z0-9]+/', $replace, $result);
return $result;
}
I guess this could be simplified more but when dealing with regexes, clarity and readability is often more important than being clever or writing super-optimal code.
Let's see how it works:
/^[^A-Za-z0-9]+/:
^ matches the beginning of the string.
[^A-Za-z0-9] matches all non-alphanumeric characters
+ means "match one or more of the previous thing"
/[^A-Za-z0-9]+$/:
same thing as above, except $ matches the end of the string
/[^A-Za-z0-9]+/:
same thing as above, except it matches mid-string too
EDIT: OP is right that the first two can be replaced with a call to trim():
function clean($string, $replace){
// Replace all consecutive occurrences of "not OK"
// characters with the replacement:
$result = preg_replace('/[^A-Za-z0-9]+/', $replace, $result);
return trim($result, $replace);
}
I don't want to sound super-clever, but I would not call it regex-foo.
What you do is actually pretty much in the right direction because you use preg_quote, many others are not even aware of that function.
However probably at the wrong place. Wrong place because you quote for characters inside a character class and that has (similar but) different rules for quoting in a regex.
Additionally, regular expressions have been designed with a case like yours in mind. That is probably the part where you look for a wizard, let's see some options how to make your negative character class more compact (I keep the generation out to make this more visible):
[^0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]
There are constructs like 0-9, A-Z and a-z that can represent exactly that. As you can see - is a special character inside a character class, it is not meant literal but as having some characters from-to:
[^0-9A-Za-z]
So that is already more compact and represents the same. There are also notations like \d and \w which might be handy in your case. But I take the first variant for a moment, because I think it's already pretty visible what it does.
The other part is the repetition. Let's see, there is + which means one or more. So you want to replace one or more of the non-matching characters. You use it by adding it at the end of the part that should match one or more times (and by default it's greedy, so if there are 5 characters, those 5 will be taken, not 4):
[^0-9A-Za-z]+
I hope this is helpful. Another step would be to also just drop the non-matching characters at the beginning and end, but it's early in the morning and I'm not that fluent with that.
How can I replace a string starting with 'a' and ending with 'z'?
basically I want to be able to do the same thing as str_replace but be indifferent to the values in between two strings in a 'haystack'.
Is there a built in function for this? If not, how would i go about efficiently making a function that accomplishes it?
That can be done with Regular Expression (RegEx for short).
Here is a simple example:
$string = 'coolAfrackZInLife';
$replacement = 'Stuff';
$result = preg_replace('/A.*Z/', $replacement, $string);
echo $result;
The above example will return coolStuffInLife
A little explanation on the givven RegEx /A.*Z/:
- The slashes indicate the beginning and end of the Regex;
- A and Z are the start and end characters between which you need to replace;
- . matches any single charecter
- * Zero or more of the given character (in our case - all of them)
- You can optionally want to use + instead of * which will match only if there is something in between
Take a look at Rubular.com for a simple way to test your RegExs. It also provides short RegEx reference
$string = "I really want to replace aFGHJKz with booo";
$new_string = preg_replace('/a[a-zA-z]+z/', 'boo', $string);
echo $new_string;
Be wary of the regex, are you wanting to find the first z or last z? Is it only letters that can be between? Alphanumeric? There are various scenarios you'd need to explain before I could expand on the regex.
use preg_replace so you can use regex patterns.