regex increment back reference by one - php

I need to validate an input with the following pattern in php:
(4 digits)/(previous number + 1)
The first digit needs to be a 1 or a 2.
As an Example:
2018/2019 //valid
2000/2010 //invalid
1999/2000 //valid
2020/2019 //invalid
I've managed to get that both groups are equal, but I can't figure out how to increment the back reference by one...
/([1-2]\d{3})\/(\1)/
The (\1) needs to be incremented by one.
Is this possible with regex?

You want to first validate the string is in <BOS><YEAR>/<YEAR><EOS> format and then check if the second year is an incremented first year.
You may use ^([12]\d{3})/([12]\d{3})\z regex (see demo) to match and validate the string, and also capture the first year into Group 1 and the second year into Group 2.
Use
$strs = ['2018/2019', '2000/2010','1999/2000','2020/2019', 'aaaa'];
foreach ($strs as $s) {
if (preg_match('~^([12]\d{3})/([12]\d{3})\z~', $s, $m)) {
if ((int)$m[2] - (int)$m[1] == 1) {
echo $s . " is valid!" . PHP_EOL;
} else {
echo $s . " is NOT valid!" . PHP_EOL;
}
} else {
echo $s . " is NOT valid!" . PHP_EOL;
}
}
See the PHP demo, output:
2018/2019 is valid!
2000/2010 is NOT valid!
1999/2000 is valid!
2020/2019 is NOT valid!
aaaa is NOT valid!

Related

Finding how many digits does every number has in an array in php [duplicate]

This question already has answers here:
PHP Count the lenght of each value in a array/string (tags)
(3 answers)
Closed 1 year ago.
I have an array which has several numbers.
What I want to do is get a loop and run into this array and count how many two-digits numbers, three-digits, four-digits numbers do I have.
What I have tried:
$myArray = array(123,1234,12345,123456,123567);
for($i=1,$size=count($myArray);$i<=$size;i++)
{
if(strlen($i==3)) echo "the number with index " .$i. " is three-digit number.";
else if(strlen($i==4)) echo "the number with index " .$i. " is four-digit number.";
...
}
I also tried this:
$threeDigits=0;
$fourDigits=0;
$fiveDigits=0;
$sixDigits=0;
$myArray=(123,1234,12345,123456,1234567,111,222)
for($i=1,$size=count($myArray);$i<=$size;i++)
{
if(strlen($==3)) $threeDigits++;
else if(strlen($i==4)) $fourDigits++;
else if(strlen($i==5)) $fiveDigits++;
else if(strlen($i==6)) $sixDigits++;
}
echo "There are " .$fourDigits. " numbers with 4 digits.";
echo "There are " .$threeDigits. " numbers with 3 digits.";
echo "There are " .$fiveDigits. " numbers with 5 digits.";
echo "There are " .$sixDigits. " numbers with 6 digits.";
But somehow it only reads them as one. As you can see, in my array there are three three-digit numbers but when I print it out it says I have only one. What do you think it might be the problem here?
Just for the hell of it, map it as a callback:
foreach(array_map('strlen', $myArray) as $key => $len) {
echo "the number with index $key is a $len digit number.";
}
Store the lengths in an array:
$myArray = array(123,1234,12345,123456,123567);
$lengths = [];
foreach ( $myArray as $val ) {
$lengths[strlen($val)]++;
}
foreach (range(2,4) as $len) {
echo "There are " . $lengths[$len] . " $len-digit numbers\n";
}

setting limit of preg_match in php 7.2

I have issue in php preg_match..
I tried using preg_match to check this string..
$txt = 'dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.catdog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog.cat.dog';
echo count(explode('.', $txt)) . "<br>";
echo strlen($txt) , "<br>";
if(preg_match("/[a-z]+(?:([.][a-z]+)*)/i", $txt)) {
echo "A match was found.";
} else {
echo "A match was not found.";
}
But I think there is limit in preg_match.. the total count after I explode the dot is 1638, more than 1638, it returns not match.
But when I tried using phpliveregex or regex 101 it can match the regex..
so here is the complete explanation..
I created a program for checking a format..
continue from this issue Javascript string match specific regex
User can input anything in textarea, as long as it's correct then it will retrive the data, but when user input wrong format, I should remove the wrong format by using preg_replace and retrive a correct format, when none of format is correct, then it will return error message..
this not 1 format only, there are about 10 formats I should check..
so this is not just a simple to explode the ., +, * or use cytpe_alpha().
The conclusion is the program or the product owner does not care what user input into the text area, they can input 10 formats into the textarea.. as long as I can check and passed the format, then it all be good..
example of wrong input that I should fix into correct format..
150-50-30----20=50+dog......cat.......cow.....chicken,,,,.,.,pencil,
dog,,,.,cat.,.,.chicken......50-20-10-5=15+1*2*3*4=24+50-50*30*20=0+*4*8=32
so after I correct the format, it will be like this..
150-50-30-20=50+dog.cat.cow.chicken.pencil.dog.cat.chicken.50-20-10-5=15+1*2*3*4=24+50-50*30*20=0+4*8=32
can anyone help with this issue?
It appears that you have reached the memory limit on "capturing". If you simply don't capture any substrings, you'll be just fine.
Code: (Demo)
$txt = 'dog.cat' . str_repeat('.dog.cat', 815);
for ($i = 0; $i < 5; ++$i) {
$txt .= '.dog.cat';
echo count(explode('.', $txt)) . "\n";
echo strlen($txt) . "\n";
if (preg_match("/[a-z]+(?:\.[a-z]+)*/i", $txt, $match)) {
echo "A match was found." . strlen($match[0]);
} else {
echo "A match was not found.";
}
echo "\n---\n";
}
Output:
1634
6535
A match was found.6535
---
1636
6543
A match was found.6543
---
1638
6551
A match was found.6551
---
1640
6559
A match was found.6559
---
1642
6567
A match was found.6567
---
About the error: https://3v4l.org/RjfiN#v7.2.0
You are getting error constant 6.
PREG_JIT_STACKLIMIT_ERROR
preg_last_error_msg() isn't available until PHP8.
I see some good answers at: PHP PREG_JIT_STACKLIMIT_ERROR - inefficient regex
If preg_match() is proving to be unsuitable/miserable for your requirements, then stop using it. There are other available tools to determine if a string is strictly comprised of dot-separated alphabetical substrings.
function isDotSeparatedAlphabetical($string) {
foreach (explode('.', $string) as $word) {
if (!ctype_alpha($word)) {
return false;
}
}
return true;
}
$txt = 'dog.cat' . str_repeat('.dog.cat', 815);
for ($i = 0; $i < 5; ++$i) {
$txt .= '.dog.cat';
var_export(['length' => strlen($txt), 'verdict' => isDotSeparatedAlphabetical($txt)]);
echo "\n---\n";
}

Using preg_replace() To Increment a Digit in a Phrase [duplicate]

I have a string formed up by numbers and sometimes by letters.
Example AF-1234 or 345ww.
I have to get the numeric part and increment it by one.
how can I do that? maybe with regex?
You can use preg_replace_callback as:
function inc($matches) {
return ++$matches[1];
}
$input = preg_replace_callback("|(\d+)|", "inc", $input);
Basically you match the numeric part of the string using the regex \d+ and replace it with the value returned by the callback function which returns the incremented value.
Ideone link
Alternatively this can be done using preg_replace() with the e modifier as:
$input = preg_replace("|(\d+)|e", "$1+1", $input);
Ideone link
If the string ends with numeric characters it is this simple...
$str = 'AF-1234';
echo $str++; //AF-1235
That works the same way with '345ww' though the result may not be what you expect.
$str = '345ww';
echo $str++; //345wx
#tampe125
This example is probably the best method for your needs if incrementing string that end with numbers.
$str = 'XXX-342';
echo $str++; //XXX-343
Here is an example that worked for me by doing a pre increment on the value
$admNo = HF0001;
$newAdmNo = ++$admNo;
The above code will output HF0002
If you are dealing with strings that have multiple number parts then it's not so easy to solve with regex, since you might have numbers overflowing from one numeric part to another.
For example if you have a number INV00-10-99 which should increment to INV00-11-00.
I ended up with the following:
for ($i = strlen($string) - 1; $i >= 0; $i--) {
if (is_numeric($string[$i])) {
$most_significant_number = $i;
if ($string[$i] < 9) {
$string[$i] = $string[$i] + 1;
break;
}
// The number was a 9, set it to zero and continue.
$string[$i] = 0;
}
}
// If the most significant number was set to a zero it has overflowed so we
// need to prefix it with a '1'.
if ($string[$most_significant_number] === '0') {
$string = substr_replace($string, '1', $most_significant_number, 0);
}
Here's some Python code that does what you ask. Not too great on my PHP, but I'll see if I can convert it for you.
>>> import re
>>> match = re.match(r'(\D*)(\d+)(\D*)', 'AF-1234')
>>> match.group(1) + str(int(match.group(2))+1) + match.group(3)
'AF-1235'
This is similar to the answer above, but contains the code inline and does a full check for the last character.
function replace_title($title) {
$pattern = '/(\d+)(?!.*\d)+/';
return preg_replace_callback($pattern, function($m) { return ++$m[0]; }, $title);
}
echo replace_title('test 123'); // test 124
echo replace_title('test 12 3'); // test 12 4
echo replace_title('test 123 - 2'); // test 123 - 3
echo replace_title('test 123 - 3 - 5'); // test 123 - 3 - 6
echo replace_title('123test'); // 124test

I would like to be able to generate a fill in the blank from a word missing 2 letters randomly

$word = "superman";
I would like to be able to randomly choose 2 letters from what ever word is in $word and build a fill in the blank box for me to be able to answer
example some how random picks the p and the a
su_erm_n comes up so I would fill in the first box with p and the second one with a I guess with a form
$wordfinished = "su" . $fillinblank1 . "erm" . $fillinblank2 . "n";
if ($wordfinshed == $word) {
echo "congrats";
}
else{
echo "try again";
}
I am just learning php I have some things that I have done that are very complicated but was having a hard time with the random stuff any help would help me learn this
You can use PHP's rand() function to select a random number from 0 to the length of the word you are modifying and change the character at that index to something else
For example:
$str = "superman";
$str[rand(0, strlen($str)-1)] = "_";
Assuming that the rand() function output a value of 3 for example, we'd end up with this output:
sup_rman
We can put this in a function that can be called more than once in order to make more than one blank space in the word:
function addBlank($str){
do{
$index = rand(0, strlen($str)-1);
$tmp = $str[$index];
$str[$index] = "_";
} while($tmp =! "_");
return $str;
}
This function accepts a string and after each call will replace a letter in the string with _. Each call will result in one more blank space. The variable $tmp holds the value of the string at the randomly chosen index and checks that it wasn't already a blank space, and if it was, it picks another index to try to replace.
So to put this in practice, we can call the above function multiple times and store the result back into a variable, here is example output:
$str = addBlank("superman");
//the value of $str is now sup_rman
$str = addBlank($str)
//the value of $str is now sup_r_an
$word = "superman";
$size = strlen($word) -1;
$fillinblank1 = $word[rand(0,$size)];
$fillinblank2 = $word[rand(0,$size)];
$wordfinished = "su" . $fillinblank1 . "erm" . $fillinblank2 . "n";
echo $wordfinished;
Output:
sueermun
Demo
http://ideone.com/Z66xsI

preg_match: trying to identify number formats

I'm trying to identify not only "numbers" in a string, but tag what type of number it is, such as General, Fraction, Percentile, Ratio etc.
Now if I use a tool like http://rubular.com/, my patterns appear to work fine.
Rules?
([-+]?)([0-9]+)([,+]?)([.]?) //General
([-+]?[0-9.,]+[%]) //Percent
([0-9]+[\/][0-9]+(?:st|nd|rd|th)) //Fraction
([-+]?[0-9.,]+[:][-+]?[0-9.,]+) //Ratio
Strings to check?
1
1,000
1.000
-50.5
-1:+3
1,200.6:3.9
+2:-4
1/5th
25%
25.76%
1,001%
It's when I put them in php (if/elseif) constructs I always end up with the "general" number?
if (preg_match('/([-+]?[0-9.,]+[%])/',$string)) {
echo " PERCENTILE ";
} elseif (preg_match('/([0-9]+[\/][0-9]+(?:st|nd|rd|th))/',$string)) {
echo " FRACTION ";
} elseif (preg_match('/([-+]?[0-9.,]+[:][-+]?[0-9.,]+)/',$string)) {
echo " RATIO ";
} elseif (preg_match('/([-+]?)([0-9]+)([,+]?)([.]?)/',$string)) {
echo " CARDINAL ";
} else {
echo " GENERAL ";
}
No matter what, it echos "CARDINAL".
Yes, I've tried switching the order (Card/General first, then the others).
Yes, I've tried making them independant IF()s, and in reverse order (most general first).
Nothing appears to work.
Even a Single IF checking for any of the formats simply fails.
Either my rules are stuffed - or I'm doing something blatantly wrong.
You error must come from somewhere else, I couldn't reproduce it. Try to put your code in an otherwise empty file to test it by itself and it should work fine.
Test.php:
$nums = array(
'1',
'1,000',
'1.000',
'-50.5',
'-1:+3',
'1,200.6:3.9',
'+2:-4',
'1/5th',
'25%',
'25.76%',
'1,001%'
);
foreach ($nums as $string) {
echo $string.': ';
if (preg_match('/([-+]?[0-9.,]+[%])/',$string)) {
echo " PERCENTILE ";
} elseif (preg_match('/([0-9]+[\/][0-9]+(?:st|nd|rd|th))/',$string)) {
echo " FRACTION ";
} elseif (preg_match('/([-+]?[0-9.,]+[:][-+]?[0-9.,]+)/',$string)) {
echo " RATIO ";
} elseif (preg_match('/([-+]?)([0-9]+)([,+]?)([.]?)/',$string)) {
echo " CARDINAL ";
} else {
echo " GENERAL ";
}
echo "\n";
}
$ php test.php
1: CARDINAL
1,000: CARDINAL
1.000: CARDINAL
-50.5: CARDINAL
-1:+3: RATIO
1,200.6:3.9: RATIO
+2:-4: RATIO
1/5th: FRACTION
25%: PERCENTILE
25.76%: PERCENTILE
1,001%: PERCENTILE
Try surrounding each regular expression with ^ and $ so that it matches only if it matches the entire string or line. Without these, if a regular expression matches part of a number, then that's still a match. For example, '1,000' matches your regular expression for CARDINAL numbers, /([-+]?)([0-9]+)([,+]?)([.]?)/, because it matches the substring '1,'. If you add ^ and $, as in /^([-+]?)([0-9]+)([,+]?)([.]?)$/, then it no longer matches.
<?php
function check_format($string) {
if (preg_match('/^([-+]?[0-9.,]+[%])$/',$string)) {
echo " PERCENTILE ";
} elseif (preg_match('/^([0-9]+[\/][0-9]+(?:st|nd|rd|th))$/',$string)) {
echo " FRACTION ";
} elseif (preg_match('/^([-+]?[0-9.,]+[:][-+]?[0-9.,]+)$/',$string)) {
echo " RATIO ";
} elseif (preg_match('/^([-+]?)([0-9]+)([,+]?)([.]?)$/',$string)) {
echo " CARDINAL ";
} else {
echo " GENERAL ";
}
}
array_map("check_format", array(
"1",
"1,000",
"1.000",
"-50.5",
"-1:+3",
"1,200.6:3.9",
"+2:-4",
"1/5th",
"25%",
"25.76%",
"1,001%"
));
outputs:
CARDINAL GENERAL GENERAL GENERAL RATIO RATIO RATIO FRACTION PERCENTILE PERCENTILE PERCENTILE
EDIT: This might be a better regular expression for CARDINAL numbers:
/^([-+]?)([0-9]+)(?:,?[0-9]{3})*([.]?)$/
Please have a look on this .
<?php
$num = 12.20
$num = floatval(preg_replace('/[^\d.]/', '', num));
// output will be 12.2
//it always replace zero and you have number 12.00 then output will be 12
$num = 12.00
$num = floatval(preg_replace('/[^\d.]/', '', num));
// output will be 12

Categories