Php preg_replace numbers characters - php

$my_string = '88888805';
echo preg_replace("/(^.|.$)(*SKIP)(*F)|(.)/","*",$,my_string);
This shows the first and last number like thus 8******5
But how can i show this number like this 888888**. (The last 2 number is hidden)
Thank you!
From this: 8******5
To: 888888**

I'm not sure if you have worked on this Regex pattern to do something unique. However, I will provide you with a general one that should fit your question without using your current pattern.
$my_string = '88888805';
echo preg_replace("/([0-9]+)[0-9]{2}$/","$1**",$,my_string);
Explanation:
The ([0-9]+) will match all digits, this could be replaced with \d+, it's between brackets to be captured as we are going to use it in the results.
[0-9]{2} is going to match the last 2 digits, again, it can be replaced with \d{2}, it's outside the brackets because we don't want to include them in the result. the $ after that is to indicate the end of the test, it's optional anyways.
Results:
Input: 88888805
Output: 888888**

echo preg_replace("/(.{2}$)(*SKIP)(*F)|(.)/","*",$my_string);
If it for a uni assignment, you'd probably want to do this. Basically says, don't match if its the last two characters, otherwise match.

Related

PHP Regex Regular Expressions preg_match() only allow digits with commas

I've asked and it was answered but now, after years, it doesn't work.
I've even tried online regex validators. Not sure what is going on.
Version: PHP 7.0.30 on 64Bit OS
The string should only allow digits with commas.
No commas in the beginning or end.
Spaces between commas is ok but I'd rather not allow it.
The following isn't passing
My regex is:
$DateInvoicedIDs = "1031,453,808,387,111,342,962,706,251,442,362,858,950,738,310,288,99,665,1023,30,894,112,132,148,347,895,382,94,766,683,276,1104,658,34,348,235,786,769,2";
$reg = '/[0-9\s]+(,[0-9\s]+)*[0-9]$/';
if ( preg_match($reg, $DateInvoicedIDs) ) {
echo = $DateInvoicedIDs;
} else { echo "false"; }
I'm using preg_match and getting false.
Any idea?
Test your string and pattern # https://regex101.com/r/3TVmOv/1
When that loads, you will see that there is no match highlighted.
Then add a digit to the end of your string and Whalla! This is because (,[0-9\s]+)* is matching the final 2 and [0-9]$ cannot be satisfied because another digit is required.
If I understand your logic/requirements, I think I'd use ~^\d+(?:\s*,\s*\d+)*$~
This improves the validation because it doesn't allow a mixture of digits and spaces between commas like: 2, 3 4 56, 72 I don't think you want spaces in your comma-separated numerical values.
Pattern Demo
Code: (Demo)
$DateInvoicedIDs = "1031,453,808,387,111,342,962,706,251,442,362,858,950,738,310,288,99,665,1023,30,894,112,132,148,347,895,382,94,766,683,276,1104,658,34,348,235,786,769,2";
$reg = '/^\d+(?:\s*,\s*\d+)*$/';
if (preg_match($reg, $DateInvoicedIDs)) {
echo $DateInvoicedIDs;
} else {
echo "false";
}
It is not matching because of the last [0-9] in your regex. The * in (,[0-9\s]+)* is a greedy match which means that it is consuming all commas followed by digits in your string. There is nothing left after to match against the last [0-9].
So you probably want to reduce your regex to '/[0-9\s]+(,[0-9\s]+)*$/.
The last part of your regex [0-9]$ is what's causing it to fail:
[0-9\s]+ is matching the first number only 1031,
(,[0-9\s]+)* is covering everything until ,2 because it's a single number right after a comma which is what it's looking for
Then [0-9]$ is trying to find one more number but it can't
If the last number is a double-digit number, i.e. ,25 instead of 2, then the that second part (,[0-9\s]+)* would be satisfied because it found at least one number and [0-9]$ would match the next number which is 5 (https://regex101.com/r/0XbHsw/1)
Adding ? for that last part would solve the problem: [0-9\s]+(,[0-9\s]+)*[0-9]?$

How can I get all occurrences of this pattern with the regex of PHP?

How can I get, into an array, all occurrences of this pattern 4321[5-9][7-9]{6} but excluding, for example, the occurrences where there is a digit immediately before the value, or immediately after it?
For instance, 43217999999 should be valid but 143217999999 (note the number 1 at the beginning) should not be valid.
As the first example, 432179999991 shouldn't be valid because of the 1 that it has in the end.
The added difficulty, at least for me, is that I have to parse this in whatever position I can find it inside a string.
The string looks like this, literally:
43217999997 / 543217999999 // 43217999998 _ 43217999999a43216999999-43216999999 arandomword 432159999997
As you would be able to note, it has no standard way of separating the values (I marked in bold the values that would make it invalid, so I shouldn't match those)
My idea right now is something like this:
(\D+|^)(4321[5-9][7-9]{6})(\D+|$)
(\D+|^) meaning that I expect in that position the start of the string or at least one non-digit and (\D+|$) meaning that I expect there the end of the string or at least one non-digit.
That obviously doesn't do what I picture in my head.
I also tried do it in two steps, first:
preg_match_all("/\D+4321[5-9][7-9]{6}\D+|4321[5-9][7-9]{6}\D+|4321[5-9][7-9]{6}$/", $input, $outputArray);
and then:
for($cont = 0; $cont < count($outputArray); $cont++) {
preg_match("/4321[5-9][7-9]{6}/", $outputArray[0][$cont], $outputArray2[]);
}
so I can print
echo "<pre>" . print_r($outputArray2, true) . "</pre>";
but that doesn't let me exclude the ones that have a number before the start of the value (5432157999999 for example), and then, I am not making any progress with my idea.
Thanks in advance for any help.
If you literally want to check if there is no digit before or after the match you can use negative look ahead and look behind.
(?![0-9]) at the end means: "is not followed by 0-9"
(?<![0-9]) at the start means: "is not preceded by 0-9"
See this example https://regex101.com/r/6xbmJk/1

Retrieve 0 or more matches from comma separated list inside parenthesis using regex

I am trying to retrieve matches from a comma separated list that is located inside parenthesis using regular expression. (I also retrieve the version number in the first capture group, though that's not important to this question)
What's worth noting is that the expression should ideally handle all possible cases, where the list could be empty or could have more than 3 entries = 0 or more matches in the second capture group.
The expression I have right now looks like this:
SomeText\/(.*)\s\(((,\s)?([\w\s\.]+))*\)
The string I am testing this on looks like this:
SomeText/1.0.4 (debug, OS X 10.11.2, Macbook Pro Retina)
Result of this is:
1. [6-11] `1.0.4`
2. [32-52] `, Macbook Pro Retina`
3. [32-34] `, `
4. [34-52] `Macbook Pro Retina`
The desired result would look like this:
1. [6-11] `1.0.4`
2. [32-52] `debug`
3. [32-34] `OS X 10.11.2`
4. [34-52] `Macbook Pro Retina`
According to the image above (as far as I can see), the expression should work on the test string. What is the cause of the weird results and how could I improve the expression?
I know there are other ways of solving this problem, but I would like to use a single regular expression if possible. Please don't suggest other options.
When dealing with a varying number of groups, regex ain't the best. Solve it in two steps.
First, break down the statement using a simple regex:
SomeText\/([\d.]*) \(([^)]*)\)
1. [9-14] `1.0.4`
2. [16-55] `debug, OS X 10.11.2, Macbook Pro Retina`
Then just explode the second result by ',' to get your groups.
Probably the \G anchor works best here for binding the match to an entry point. This regex is designed for input that is always similar to the sample that is provided in your question.
(?<=SomeText\/|\G(?!^))[(,]? *\K[^,)(]+
(?<=SomeText\/|\G) the lookbehind is the part where matches should be glued to
\G matches where the previous match ended (?!^) but don't match start
[(,]? *\ matches optional opening parenthesis or comma followed by any amount of space
\K resets beginning of the reported match
[^,)(]+ matches the wanted characters, that are none of ( ) ,
Demo at regex101 (grab matches of $0)
Another idea with use of capture groups.
SomeText\/([^(]*)\(|\G(?!^),? *([^,)]+)
This one without lookbehind is a bit more accurate (it also requires the opening parenthesis), of better performance (needs fewer steps) and probably easier to understand and maintain.
SomeText\/([^(]*)\( the entry anchor and version is captured here to $1
|\G(?!^),? *([^,)]+) or glued to previous match: capture to $2 one or more characters, that are not , ) preceded by optional space or comma.
Another demo at regex101
Actually, stribizhev was close:
(?:SomeText\/([^() ]*)\s*\(|(?!^)\G),?\s*([^(),]+)(?=[^()]*\))
Just had to make that one class expect at least one match
(?:SomeText\/([0-9.]+)\s*\(|(?!^)\G),?\s*([^(),]+)(?=[^()]*\)) is a little more clear as long as the version number is always numbers and periods.
I wanted to come up with something more elegant than this (though this does actually work):
SomeText\/(.*)\s\(([^\,]+)?\,?\s?([^\,]+)?\,?\s?([^\,]+)?\,?\s?([^\,]+)?\,?\s?([^\,]+)?\,?\s?([^\,]+)?\,?\s?\)
Obviously, the
([^\,]+)?\,?\s?
is repeated 6 times.
(It can be repeated any number of times and it will work for any number of comma-separated items equal to or below that number of times).
I tried to shorten the long, repetitive list of ([^\,]+)?\,?\s? above to
(?:([^\,]+)\,?\s?)*
but it doesn't work and my knowledge of regex is not currently good enough to say why not.
This should solve your problem. Use the code you already have and add something like this. It will determine where commas are in your string and delete them.
Use trim() to delete white spaces at the start or the end.
$a = strpos($line, ",");
$line = trim(substr($line, 55-$a));
I hope, this helps you!

Quick PHP regex for digit format

I just spent hours figuring out how to write a regular expression in PHP that I need to only allow the following format of a string to pass:
(any digit)_(any digit)
which would look like:
219211_2
so far I tried a lot of combinations, I think this one was the closest to the solution:
/(\\d+)(_)(\\d+)/
also if there was a way to limit the range of the last number (the one after the underline) to a certain amount of digits (ex. maximal 12 digits), that would be nice.
I am still learning regular expressions, so any help is greatly appreciated, thanks.
The following:
\d+_\d{1,12}(?!\d)
Will match "anywhere in the string". If you need to have it either "at the start", "at the end" or "this is the whole thing", then you will want to modify it with anchors
^\d+_\d{1,12}(?!d) - must be at the start
\d+_\d{1,12}$ - must be at the end
^\d+_\d{1,12}$ - must be the entire string
demo: http://regex101.com/r/jG0eZ7
Explanation:
\d+ - at least one digit
_ - literal underscore
\d{1,12} - between 1 and 12 digits
(?!\d) - followed by "something that is not a digit" (negative lookahead)
The last thing is important otherwise it will match the first 12 and ignore the 13th. If your number happens to be at the end of the string and you used the form I originally had [^\d] it would fail to match in that specific case.
Thanks to #sln for pointing that out.
You don't need double escaping \\d in PHP.
Use this regex:
"/^(\d+)_(\d{1,12})$/"
\d{1,12} will match 1 to 12 digist
Better to use line start/end anchors to avoid matching unexpected input
Try this:
$regex= '~^/(\d+)_(\d+)$~';
$input= '219211_2';
if (preg_match($regex, $input, $result)) {
print_r($result);
}
Just try with following regex:
^(\d+)_(\d{1,12})$

Search a String for Alpha Numeric Characters in a Pattern

I have a string that contains 5 words. In the string one of the words is a Ham Radio Call Sign and can be anyone of the thousands of call signs in the US. In order to extract the Call Sign from the string I need to utilize the below pattern. The Call Sign I need to extract can be in any of the 5 positions in the string. The number is never the first character and the number is never the last character. The string is actually put together from an Array since it is originally read from a text file.
$string = $word[1] $word[2] $word[3] etc....
So the search can be either done on the whole string or each piece of the array.
Patterns:
1 Number and 3 Letters Example: AB4C A4BC
1 Number and 4 Letters Example: A4BCD
1 Number and 5 Letters Example: AB4CDE
I have tried everything I can think of and search till I cant search no more. I am sure I am over thinking this.
A two-step regular expression like this would do it:
$str = "hello A4AB there BC5AD";
$signs = array();
preg_match_all('/[A-Z][A-Z\d]{1,3}[A-Z]/', $str, $possible_signs);
foreach($possible_signs[0] as $possible_sign)
if (preg_match('/^\D+\d\D+$/', $possible_sign))
array_push($signs, $possible_sign);
print_r($signs); //Array ([0] => A4AB [1] => BC5AD)
Explanation
This is a regular expression approach, using two patterns. I don't think it could be done with one and still satisfy the exact requirements of the matching rules.
The first pattern enforces the following requirements:
substring starts and ends with a capital letter
substring contains only other capital letters or numbers between the first and last letter
substring is, overall, not more than 6 characters long
What I can't do in that same pattern, for complex REGEX reasons I won't go into (unless someone knows a way and can correct me), is enforce that only one number is contained.
#jeroen's answer does enforce this in a single pattern, but in turn does not enforce the correct length of the substring. Either way, we need a second pattern.
So after grabbing the initial matches, we loop over the results. We then apply each to a second pattern that enforces simply that there is only one number in the substring.
If so, we green-light the substring and it's added to the $signs array.
Hope this helps.
It depends on what the other words can contain, but you could use a regular expression like:
#\b[a-z]+\d[a-z]+\b#i
^ case insensitive
^^ a word boundary
^^^^^^ One or more letters
^^ One number
You can make it more restrictive by using {1,3} instead of + for the letters so that you have a sequence of 1 to 3 letters.
The complete expression would be something like:
$success = preg_match('#\b[a-z]+\d[a-z]+\b#i', $input_string, $matches);
where $matches[0] will contain the matched value, see the manual.

Categories