Regular expression for limiting character not working - php

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.

Related

php validate phone number

I need help with form validation. Specifically for Australian phone numbers. I can only do basic validation using the preg_match() method but I'm stuck with this.
Must start with +614, (04) or 04; then any grouping of 8 more digits
and single spaces is permitted.
That's the validation criteria, any help is appreciated.
if (!preg_match("/^[0-9 ]*$/",$name)) {
$numberErr = "Number format is invalid"
}
that's all I can do I don't know how to add conditions for the start of the number (start with +614, (04) or 04.
Edit: Also need help with credit card validation, validation criteria is:
Any grouping of 12 - 19 numbers and single spaces are permitted.
if(!preg_match('/[0-9]{12}(?:[0-9]{3})?$/', $card)) {
$cardErr = "Invalid card number";
}
I can't find anything that teaches preg_match() method parameters so I honestly don't even know what the above code is doing.
Sorry for my noobness ;)
I am using anchors (^ and $) so that the start and the end of the string are identified. The leading characters are in the first non-capturing group with pipes that represent "OR". The second non-capturing group, contains the "space-tolerant" 8-digit substring.
Let me know if you have any fringe cases that are not handled properly.
Code: (Demo)
$aussie_mobiles = ['+614 1234 5678', '02 11112222', '(04)98765432', '0413572468', '+614 1 2 3 4 5 6 7 8'];
foreach ($aussie_mobiles as $mob) {
echo "$mob: ";
if (preg_match('~^(?:\+614|\(04\)|04)(?: *\d){8}$~', $mob)) {
echo "pass\n";
} else {
echo "fail\n";
}
}
Output:
+614 1234 5678: pass
02 11112222: fail
(04)98765432: pass
0413572468: pass
+614 1 2 3 4 5 6 7 8: pass

preg_match not working on last two charcters

i got his small code
<?php
if (preg_match("/Remanufactured|REMANUFACTURED/",$product_info['products_description'] )
|| preg_match("/N2|N3|W1|W2|A1|A2|A3|R4/",$product_info['manufacturers_code'])) {
echo "Refurbished";
} else {
echo "New Boxed";
}
?>
if $product_info['manufacturers_code'] = '2122586R4' or 'MC-MCB43112U0C2/04/1' the above code works.
I want the above code to only match where the last two characters are "/N2|N3|W1|W2|A1|A2|A3|R4/"
i have tried "/N2$|N3$|W1$|W2$|A1$|A2$|A3$|R4$/" and it doesnt work.
regards
irfan
Replace
/N2|N3|W1|W2|A1|A2|A3|R4/
With
/^(.*)(N2|N3|W1|W2|A1|A2|A3|R4)$/
.* will match any string at the beginning and the specified two string at end
Try this
preg_match('/(N2|N3|W1|W2|A1|A2|A3|R4)$/',$product_info['manufacturers_code'])
( ) - Groups a series of pattern elements to a single element.
| - Separates alternate possibilities.
$ - Matches the end of a line or string.
so "(a|b)" means "a or b". "(a|b)$" means "a or b" at the end of a line or string.

Check if a string contains a set of characters at the end of a string

I have a simple problem, but has become a troublesome problem:
$variable="This is some text***";
if (strpos($variable,'*') !== false) {
echo 'found *';
} else {
echo 'not found *';
}
But it will find a * in the text no matter how many *s there are.
I want to make it only can be found by searching specified star, *** (three stars) instead only * (one star).
To make it even more strict matching, that you only want it to match a string that contains *** at the end of the string you can use regex, so,
if (preg_match('~[^*]\*{3}$~', $str)) {
print "Valid";
}
What this says is when a string has 3 stars at the end and there are no asterisks before those 3 stars then it will be true. Change the 3 to a 2 or 1 or whatever number of stars you want to match.
[^*] means that there can be a character but it cannot be a star that is followed by 3 stars. \*{3} means it will match 3 stars. The backslash is to escape asterisk for the pattern match and 3 is the number of total stars.
It could be a function like this:
function starMatch($str, $count) {
return (bool)preg_match('~[^*]\*{'.$count.'}$~', $str);
}
And called like this:
starMatch($str, 1); // matches *
starMatch($str, 2); // matches **
starMatch($str, 3); // matches ***

Using a string as a table to swap alphabet letters

I am trying to take each characters in a sentence and change them to a different one to "encode" the sentence (More like just make it unreadable).
The idea is to take this string : "abc" and turn each characters in it into the next one in the alphabet, giving "bcd". So on an 'A' becomes a 'B' and a 'Z' becomes an 'A' when you reach the end. I created this code which indeed works, but only if you're trying to turn a 'B' into an 'A' which is going backwards in the alphabet.
Here is the code that works (turns B's into A's) :
<?php
$SentenceToEncode="hello stackoverflow, this is my first question. thanks for helping!";
$Alphabet="abcdefghijklmnopqrstuvwxyz";
$ModifiedAlphabet="zabcdefghijklmnopqrstuvwxy";
$SentenceLength=strlen($SentenceToEncode);
for($i=0;$i<$SentenceLength;$i++){
for($j=0;$j<26;$j++){
if($SentenceToEncode[$i]===$Alphabet[$j]){
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
}
}
}
echo $SentenceToEncode;
?>
Which results in this when I run it :
gdkkn rsybjnudqeknv, sghr hr lx ehqrs ptdrshnm. sgymjr enq gdkohmf!
But when I try this second block that turns A's into B's (which is what I want) :
<?php
$SentenceToEncode="hello stackoverflow, this is my first question. thanks for helping!";
$Alphabet="abcdefghijklmnopqrstuvwxyz";
$ModifiedAlphabet="bcdefghijklmnopqrstuvwxyza";
$SentenceLength=strlen($SentenceToEncode);
for($i=0;$i<$SentenceLength;$i++){
for($j=0;$j<26;$j++){
if($SentenceToEncode[$i]===$Alphabet[$j]){
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
}
}
}
echo $SentenceToEncode;
?>
I get this :
aaaaa aaaaaaaaaaaaa, aaaa aa aa aaaaa aaaaaaaa. aaaaaa aaa aaaaaaa!
Where did I go wrong? The only difference being the modified alphabet's first and last two letters.
Thanks in advance!
You have to add a break; in your if statement (I would do it for both scripts to save some iterations)! Like this:
if($SentenceToEncode[$i]===$Alphabet[$j]) {
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
break;
}
Why?
Because if you don't do this it runs the inner loop 26 times for every character! So what that means is:
It first searches the letter h in the normal alphabet and it will find it at position 7. So now it's going to replace the first letter with the letter in the modified alphabet at position 7 which is i. BUT now you don't break the inner loop and it's going for the next iteration to search the first letter, which is now i in the normal alphabet and i is exactly the next letter in the inner loop.
So you replace every character to the end of the modified alphabet! (This didn't happened to you in the first time, because you moved it backwards so it couldn't find it again)
You can do it much easier using str_replace function.
$decoded = array("a", "b", "c", ...., "z");
$encoded = array("z", "a", "b", ...., "y");
$encoded_text = str_replace($decoded, $encoded, $original_text);
$decoded_text = str_replace($encoded, $decoded, $encoded_text);
You can also create initial arrays from strings using str_split function
Try this. You need to execute the second loop as soon it matches the alphabet.
<?php
$SentenceToEncode="hello stackoverflow, this is my first question. thanks for helping!";
$Alphabet="abcdefghijklmnopqrstuvwxyz";
//$ModifiedAlphabet="zabcdefghijklmnopqrstuvwxy";
$ModifiedAlphabet="bcdefghijklmnopqrstuvwxyza";
$SentenceLength=strlen($SentenceToEncode);
for($i=0;$i<$SentenceLength;$i++){
for($j=0;$j<strlen($ModifiedAlphabet);$j++){
if($SentenceToEncode[$i]===$Alphabet[$j]){
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
break;
}
}
}
echo $SentenceToEncode;
?>

PHP preg_match for dimension

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.

Categories