I was searching for hours to get a regular expression for matching dimension in a string.
Consider following types of strings,
120x200
100' X 130'
4 acres
0.54
0.488 (90x223)/ GIS0.78
90x160
100x149.7
143.76 X 453.52
6.13 per tax bill
120x378 per tax roll
I want the O/P contain only dimensions, even with 'X' or 'x'
From the above string, the expected output is,
120x200,100' X 130',0,0,90x223,90x160,100x149.7,143.76 X 453.52,0,120x378
Is there any possible reg-ex? or any other alternative?
Thanks
This seems to work:
<?php
$str = <<<EOD
120x200
100' X 130'
4 acres
0.54
0.488 (90x223)/ GIS0.78
90x160
100x149.7
143.76 X 453.52
6.13 per tax bill
120x378 per tax roll
EOD;
$lines = explode("\n", $str);
foreach($lines as $line) {
if (preg_match('/-?(\d+(?:\.\d+)?(\'|ft|yd|m|")?)\s*x\s*-?(\d+(?:\.\d+)?(?:\\2)?)/i', $line, $match)) {
echo "{$match[1]}x{$match[3]}\n";
} else {
echo "0\n";
}
}
You can add more units of measurement into the 3rd parenthesized expression if you want to match more things, but this matches whole numbers, real numbers, and optional units of measurement after.
This should get you started:
\d+(\.\d+)?['"]?\s*[xX]\s*\d+(\.\d+)?['"]?
demo : http://regexr.com?386sf
However,it does not cover all of your cases,as they are too customized to be handled by regex.
I would recommend using a customized method to parse the input with different cases.
Related
I have a bunch of emails that I read as text in my program and they all have phone numbers such as these:
+370 655 54298
+37065782505
37069788505
865782825
65782825
(686) 51852
How would I go about finding them and saving it into a variable?
For now I am doing it like this:
$found = preg_match('^[0-9\-\+]{9,15}^', $text, $num);
But it does not working at all
Have a look at the "libphonenumber" Google Library.
There are two functions you may find useful
isPossibleNumber - quickly guessing whether a number is a possible phonenumber by using only the length information, much faster than a full validation.
isValidNumber - full validation of a phone number for a region using length and prefix information.
This should work https://regex101.com/r/E2PzRN/2
#\+?\(?\d+\)?\s?\d+\s?\d+#
<?php
$regex = '#\+?\(?\d+\)?\s?\d+\s?\d+#';
$x = [
'+370 655 54298',
'+37065782505',
'37069788505',
'865782825',
'hjtgfjtdfjtgdfjt',
'65782825',
'(686) 51852',
];
foreach ($x as $y) {
if (preg_match($regex, $y, $match)) {
echo $match[0] . "\n";
}
}
Check it in action here https://3v4l.org/6AlQa
We distinguish here 3 types of phone numbers.
The first type is this one:
+37065782505
37069788505
865782825
65782825
Here, the beginning + is optional. we thus consider that we have 7 digits minimum for these numbers.
The regular expression obtained is therefore
(\+?[0-9]{7,})
The second type is this one:
+370 655 54298
Here we have a first block consisting of a + followed by 2 to 6 digits and then several other blocks of 2 to 6 digits and separated by spaces.
The regular expression obtained is therefore
(\+[0-9]{2,6}(\s[0-9]{2,6})+)
The last type is this one:
(686) 51852
This is a first block consisting of 2 to 6 digits surrounded by parentheses and then several other blocks of 2 to 6 digits and separated by spaces.
The regular expression obtained is therefore
(\([0-9]{2,6}\)(\s[0-9]{2,6})+)
The complete extraction code is therefore
preg_match_all("#(\+?[0-9]{7,})|(\+[0-9]{2,6}(\s[0-9]{2,6})+)|(\([0-9]{2,6}\)(\s[0-9]{2,6})+)#",$text,$out);
$found = $out[0];
where $found is an array.
I would suggest stripping out '+','(',')',' ' and testing if it is a ctype_digit
remove all characters and test if numeric, this assumes that the result is a phone no, if you were to run this on an email address the result would be false
var_dump(ctype_digit(str_replace([' ', '+', '(', ')'], '', '(686) 51852')));
TRUE
var_dump(ctype_digit(str_replace([' ', '+', '(', ')'], '', 'r#pm.mr')));
FALSE
I want to limit the number of "b" between 1 and 6, for which I'm using the following code:
<?php
$str="Big black books being kept in a black bag of a beautiful babe";
$pattern="/(b){1,6}/";
if(!preg_match($pattern,$str,$matches))
{
echo "Please use six bs";
}else
{/*do nothing*/}
print_r($matches);
?>
But It's not working. What am I doing wrong?
Through regex alone..
$str="Big black books being kept in a black bag of a beautiful babe";
$pattern="/^([^b]*b){1,6}[^b]*$/";
if(!preg_match($pattern,$str,$matches))
{
echo "Please use upto six bs";
}else
{/*do nothing*/}
print_r($matches);
and note that this must except atleast one single b. If you want to match also the line which don't have any single b then use /^([^b]*b){0,6}[^b]*$/
Add case-insensitive modifier i if you want to count also for capital B's.
Explanation:
^ start of the line.
([^b]*b){1,6} It matches (zero or more non-b characters and a b)(from 1 to 6 times). So this ensures that there must be character b exists min of 1 time and a max of 6 times.
[^b]* Matches any char but not of b, zero or more times. This ensures that there are no more further b exists.
$ End of the line boundary..
Try using match count.
<?php
$str="Big black books being kept in a black bag of a beautiful babe";
preg_match_all("/(b)/i",$str,$matches);
if(isset($matches[1]) && count($matches[1]) > 6 )
{
echo "Please use six bs";
}else
{/*do nothing*/}
print_r($matches);
?>
I think you want to count the number of Bs in the whole string while your regular expression counts them only in rows. i.e. "bbb" or just "b" would return a match.
Try using substr_count to achieve what I think you want. Here's an example.
<?php
$str = "Big black books being kept in a black bag of a beautiful babe";
if(substr_count($str, "b") > 6)
echo "Six is the limit...";
else
echo "Doing nothing...";
?>
But of course, it won't really help if you want to see the found matches.
I want to display an error message if the number doesn't match any number with hyphen, plus sign, space or brackets. No numbers either.
For example:
(012) 123 4567
(012)-123-4567
012-345-6789
123 123 1234
+12 23 213 3456
The above examples all work with this expression:
if (!preg_match("/^[0-9\-]|[\+0-9]|[0-9\s]|[0-9()]*$/", $_POST['tel'])) {
$telErr = "Invalid contact number";
}
But it allows letters, which I do not want.
Example:
+00000000a
The above example is accepted by the expression I have.
Please can someone help me with this.
I first cleanup the string a bit (that avoids useless matches):
$input = preg_replace('/[^0-9+\(\)-]/', '', $_POST['tel']);
I than match an american number +1 (xxx) xxx-xxxx;
if(preg_match('/^(\+1|001)?\(?([0-9]{3})\)?([ .-]?)([0-9]{3})([ .-]?)([0-9]{4})/',$input))
$result = "match: USA";
else $result = "no match";
this allows for quite some input configurations - only your last number would not match (if I'd not do the cleanup first, not because of the international code which is matched, but because of the split in the area-code) all the others go also without cleanup.
This expression'll accept +5number, 5number
"'^(([\+]([\d]{2,}))([0-9\.\-\/\s]{5,})|([0-9\.\-\/\s]{5,}))*$'"
Better regular expression is:
"/^[\+0-9\-\(\)\s]*$/"
It seems to me that what you want to express is in the ballpark of:
\+{0,1}\({0,1}[0-9]{0,3}\){0,1}[ -]{0,1}[0-9]{0,4}[ -]{0,1}[0-9]{0,4}[ -]{0,1}[0-9]{0,4}
that can be reduced to:
(\+?\(?[0-9]{2,3}\)?)([ -]?[0-9]{2,4}){3}
This can be read this way:
\+? //matches existence of +
\(? //matches existence of (
[0-9]{2,3} //matches 2 to 3 numbers
\)? //matches existence of )
([ -]?[0-9]{2,4}){3} //matches a space or a dash with 2 to 4 numbers, 3 times.
This will give you a maximum of 3 + 4 * 3 = 15 numbers without spaces for the phone variable.
But the best way in my opinion is to trim the input and then count it's length.
In RegEx there's always a perfect matching answer, but it doesn't always means it's a good idea to use it. It can be too complicated to maintain or too hard to understand.
SPAIN - ES
preg_match("/^(\+34|0034|34)?[6|7|9][0-9]{8}$/", $phone);
PORTUGAL - PT
preg_match("/^(\+351|00351|351)?[2|9][0-9]{8}$/", $phone);
ANDORRA - AD
preg_match("/^(\+376|00376|376)?[0-9]{6}$/", $phone);
GIBRALTAR - GI
preg_match("/^(\+350|00350|350)?[0-9]{8}$/", $phone);
--
It will be wonderfull have all the country list
My PHP script calls the Freebase API and outputs a paragraph which I then do a little bit of regex and other parsing magic on and return the data to the variable $paragraph. The paragraph is made up of multiple sentences. What I want to do is return a shorter version of the paragraph instead.
I want to display the first sentence. If it is less than 100 characters then I'd like to display the next sentence until it is at least 100 characters.
How can I do this?
You don't need a regular expression for this. You can use strpos() with an offset of 99 to find the first period at or after position 100 - and substr() to grab up to that length.
$shortPara = substr($paragraph, 0, strpos($paragraph, '.', 99) + 1);
You probably want to add a bit of extra checking in case the original paragraph is less than 100 characters, or doesn't end with a period:
// find first period at character 100 or greater
$breakAt = strpos($paragraph, '.', 99);
if ($breakAt === false) {
// no period at or after character 100 - use the whole paragraph
$shortPara = $paragraph;
} else {
// take up to and including the period that we found
$shortPara = substr($paragraph, 0, $breakAt + 1);
}
I need to validate measurements entered into a form generated by PHP.
I intend to compare them to upper and lower control limits and decide if they fail or pass.
As a first step, I imagine a PHP function which accepts strings representing engineering measurements and converts them to pure numbers before the comparison.
At the moment I'm only expecting measurements of small voltages and currents, so strings like
'1.234uA', '2.34 nA', '39.9mV'. or '-1.003e-12'
will be converted to
1.234e-6, 2.34e-9, 3.99e-2 and -1.003e-12, respectively.
But the method should be generalisable to any measured quantity.
function convert($value) {
$units = array('p' => 'e-12',
'n' => 'e-9',
'u' => 'e-6',
'm' => 'e-3');
$unitstring = implode("", array_keys($units));
$matches = array();
$pattern = "/^(-?(?:\\d*\.\\d+)|(?:\\d+))\s*([$unitstring])([a-z])$/i";
$result = preg_match($pattern, $value, $matches);
if ($result)
$retval = $matches[1].$units[$matches[2]].$matches[3];
else
$retval = $value;
return $retval;
}
So to explain what the above does:
$units is an array to map unit-prefix to the exponent.
$unitstring conglomerates the units into a single string (in the example it would be 'pnum')
The regular expression will match an optional -, followed by either 0 or more digits, a period and 1 or more digits OR 1 or more digits, followed by one of the unit prefixes (only one) and then a single alphabetical character. There can be any amount of whitespace between the number and the units.
Because of the parethesis and the use of preg_match, the number section, the unit prefix, and the unit are all separately captured in the array $matches as elements 1, 2, and 3. (0 will contain the entire string)
$result will be 1 if it matched the regex, 0 otherwise.
$retval is constructed by just connecting the number, the exponent (based on the unit prefix from the array) and the units provided, or it will just be the passed in string (such as if you're given the -1.003e-12, it will be returned)
Of course you can tweak some things, but in general this is a good start. Hope it helps.
In your function
first you need to initialize values for units like -6 for u, -3 for m...etc
divide the string in Number and Unit(i.e micro(u),mili(m),etc).
and then say the entered no is NUM; and unit is UNIT..(char like u,m etc);
while(NUM>10)
{
NUM=NUM/10;
x++; //x is keeping track of the DOT.
}
UNIT=UNIT+x; //i.e UNIT is increased(for M,K,etc) or decreased(for u,m,etc)
echo NUM.e.UNIT;
May be it will do!
My own possibly simple-minded approach has been to use an array of patterns in preg_replace
function convert($value) {
$result = preg_replace($patterns, $replacements, $value);
return $result;
}
Where
$patterns = array('/p[av]/i', '/n[av]/i', '/u[av]/i', '/m[av]/i');
$replacements = array('e-12', 'e-9', 'e-6', 'e-3');
And it could be extended to higher prefixes, but it seems heavy-handed to keep adding increasingly complex regexes to the $patterns array.
Edit: The comparison, later, should interpret the return value as a real number.
I'm hoping someone can suggest something more elegant.