interesting Regular Expression - php

Hi very interesting Regex Expression, i tried a lot of time,but some difficulties in it.
Regex rule:
user can use following characters all small([a-z]), all capital([A-Z]), numbers([0-9]) and the follownig symbols
!~*:;<>+#-£$&_?(){}[] and one space. All characers are in any order,
but restiriction are following:
input can not start with digit.
user can use zero or one white space any where in the input, but input can not start and end with white space.
input must contains at least one special following character!~*:;<>+#-£$&_?(){}[] in any order.
input length is in between 6-15.
Question: Regular expression which fullfills the above requirment. i have spent many of hours on it.but make the following Regex expression.
Regex='/^([a-zA-Z]|!|\~|*|\:|\;|\<|>|+|#|-|\£|\$|\&|_|\?|{|}|[|]|(|)){1,20}(\s){0,1}([a-zA-Z]|!|\~|*|\:|\;|\<|>|+|#|-|\d|\£|\$|\&|_|\?|{|}|[|]|(|)){1,20}(!|\~|*|\:|\;|\<|>|+|#|-|\£|\$|\&|_|\?|{|}|[|]|(|)){1,}$/i';
it fullfills all rule but not rule no.4.
complete regex which fullfills the above rules will be appreciated.

Some hints before getting to the solution.
You use the modifier i, means "case independent" matching. So no a-zA-Z needed just use a-z or A-Z.
From your list of characters [a-zA-Z]|!|\~|*|\:|\;|\<|>|+|#|-|\£|\$|\&|_|\?|{|}|[|]|(|)
There are some characters that needs escaping, since they are special in regex.
Skip the alternation and put all characters in the char class (you can also spare the escaping then)
To enforce some of your rules you need lookahead assertions
So your regex (for php) can look like:
^(?![\d ])(?![^ ]*[ ][^ ]*[ ])(?=.*[!~*:;<>+#\-£$&_?{}\[\]()])[a-z\d!~*:;<>+#\-£$&_?{}\[\]() ]{6,15}(?<![ ])$
If you need the regex for JavaScript, you can not use the lookbehind assertion. You can replace it also by a lookahead:
^(?![\d ])(?!.* $)(?![^ ]*[ ][^ ]*[ ])(?=.*[!~*:;<>+#\-£$&_?{}\[\]()])[a-z\d!~*:;<>+#\-£$&_?{}\[\]() ]{6,15}$
See it here on Regexr (Note. I have used there [^ \r]) just because I need multiline for testing)
The regex explained:
[a-z\d!~*:;<>+#\-£$&_?{}\[\]() ]{6,15} matches all characters you want to allow, in the required length.
(?![\d ]) negative lookahead assertion, that ensures the string does not start with a digit or a space.
(?![^ ]*[ ][^ ]*[ ]) negative lookahead assertion, that ensures the string does not have more than one space
(?=.*[!~*:;<>+#\-£$&_?{}\[\]()]) positive lookahead assertion, that ensures the string does have one of your special symbols
(?<![ ])$ negative lookbehind assertion, that ensures the string does not end with a space.
Unicode:
JavaScript does not support this natively!
If you want to support Unicode letters instead of only the old ASCII letters, then replace
[a-z] with \p{L}. You can then also remove the i modifier, since \p{L} is a Unicode property that matches all letters in any language (only complete letters, not combined ones, there you could use [\p{L}\p{Mn}\p{Mc}])

Here's how I'd do it.
<?php
$symbols = '!~*:;<>+#\-£$&_?(){}\[\]';
$regex = "/^(?=.*[$symbols])(?=.{6,15}\$)(?!.* )[a-zA-Z][a-zA-Z0-9 $symbols]+[a-zA-Z0-9]$";
?>
If any of the following explanations are unclear, please ask, referring to their number:
Note that we've factored out the list of symbols for convenience.
Note that we've escaped -, [, and ], as these are meaningful characters in character classes. It's possible to not escape them as long as the - is at the beginning or end, and the ] is at the beginning, but since we're mixing $symbols with other characters, we can't be sure where the "beginning" or "end" really is.
(?=...) are known as lookaheads. They're useful for asserting multiple conditions. For example, the (?=.*[$symbols]) asserts that there is a symbol somewhere (hence the .*); and the (?=.{6,15}\$) asserts that, from beginning to end, the string is between 6 and 15 characters in length (note that the $ is escaped only because it exists in a double-quote).
The (?!...) is known as a negative lookahead. The (?!.* ) asserts that there are no two consecutive spaces anywhere.
The remainder should be obvious.

Like suggested by #Juhana in the comments, why not test your rules separately rather than make a single over complex regex? something like this. (these are not actual solutions or tested as you didn't provide any test strings, more an example of how to think differently about your problem)
Javascript
function verify(string) {
var length = string.length;
if (length < 6 || length > 15 || /^\d/.test(string) || /^\s/.test(string) || /\s$/.test(string) || /\s\s/.test(string) || /[!~*:;<>+#-£$&_?(){}[\]]+/.test(string)) {
return false;
}
return true;
}
PHP
function verify($string) {
$length = strlen($string);
if ($length < 6 || $length > 15 || preg_match("/^\d/", $string) || preg_match("/^\s/", $string) || preg_match("/\s$/", $string) || preg_match("/\s\s/", $string) || preg_match("/[!~*:;<>+#-£$&_?(){}[\]]+/", $string)) {
return false;
}
return true;
}

Related

How can I check a string's pattern with given conditions (php/regex)

This is what I'm trying to do,
$line = "dsfsdf";
if (!preg_match('/^(?=.{1,30}$)[a-zA-Z0-9\-\_]*$^/', $line))
{
echo 'No Match found';
}
else
{
echo 'Match found';
}
The requirement is below,
it can have characters
it can have numbers
As special character, it can have only hyphen (-) and underscore (_) characters in it
I'm not so good at regex part. Can someone guide me how to achieve it with a simple explanation?
You must remove ^ (start of string anchor) at the end. Also, you may replace [a-zA-Z0-9_] with \w, as without any modifiers, they are equal.
The (?=.{1,30}$) lookahead makes the regex engine only match strings with 1 to 30 characters. You may remove the lookahead and just apply the limiting quantifier to your character class.
You may use
'/^[\w-]{1,30}$/'
If you prefer a more verbose way use
'/^[a-zA-Z0-9_-]{1,30}$/'
See the PHP demo.
Both mean:
^ - start of string
[\w-]{1,30} - 1 to 30 letters/digits/underscores/- symbols
$ - end of string. NOTE that to match at the very end of the string, you need to use a D modifier, or replace $ with \z anchor (i.e. use '/^[\w-]{1,30}$/D' or '/^[\w-]{1,30}\z/' then).

Regex to detect the colon and sides of it?

First see my string please:
$a = "[ child : parent ]";
How can I detect that the pattern is:
[(optional space)word or character(optional space) : (optional space)word or character(optional space)]
You can catch this as follows in PHP:
Your regular expression is /\[ *\w+ *: *\w+ *]/
You would write code that would look like this to see if it matched.
if (preg_match('/regex/', $string)) {
// do things
}
Explanation of the Regular Expression
There is a backslash (\) before the open bracket because
[ has special meaning in regular expressions. The backslash
prevents its special meaning from being used.
The asterisk (*) matches 0 or more of the previous character expression. In this
case, it matches 0 or more spaces. If you instead used the
expression \s*, it would match 0 or more white-space characters
(space, tab, line break). Finally, if you wanted it to match 0 or 1
of the previous character, you would use ? instead of *.
The plus (+) matches 1 or more of the previous character expression. The \w character expression matches a letter, digit, or underscore. If you don't want underscores to match, you should instead use a character class. For example, you could use [A-Za-z0-9].
You can find more information on regular expressions at http://www.regular-expressions.info and http://www.regular-expressions.info/php.html
From your sample text I'd say you mean a human word and not \w regex word
preg_match('/\[ ?([a-z]+) ?: ?([a-z]+) ?\]/i', $a, $matches);
Explained demo: http://regex101.com/r/hB2oV9
$matches will save both values, test with var_dump($matches);
I'm not sure on the php-specific version of regex, but this should work:
\[ ?\w+ ? : ?\w+ ?\]
Here is a site that I've used in the past to find regular expressions for my needed patterns.
use this regex \[\s*\w+\s*:\s*\w+\s*\]
I would probably do it like this
preg_match('/^\[\s?\w+\s+:\s+\w+\s?\]$/', $string)

What am I doing wrong with this Regex?

To be honest, I don't really get RegEx. So I'm completely oblivious as to where I'm going wrong here.
I'm looking for a RegEx that accepts alphanumeric characters only (and underscores, it's for usernames). I've searched around here and found numerous example RegExes that I've tried and not one of them has worked.
Among others, which I've mostly gotten from answers around here, I've tried
^[a-zA-Z0-9_]*$
/[^a-z_\-0-9]/i
/^\w+$/
To match these, I've tried (with each of the regexes)
if(preg_match("/^\w+$/", $username)) {
//don't accept
}
and
if(!preg_match("/^\w+$/", $username)) {
//don't accept
}
and
if(preg_match("/^\w+$/", $username) == 1) {
//don't accept
}
and
if(preg_match("/^\w+$/", $username) == 0) {
//don't accept
}
etc...
Each and every single time it's accepting special characters (I've tried &, $, ^, and %).
What exactly am I doing wrong here? Is it the format of the RegEx? Is it how I'm asking it to check?
Also, what exactly is the return type I get if it's found special characters? (i.e One I don't want to accept)
preg_match returns 1 if the input string matched the pattern you gave, and 0 if it didn't.
You want each character in your usernames to be alphanumeric (plus underscore). One PCRE way of expressing that is with a character class inside square brackets, like this one: [A-Za-z0-9_]. There are a couple of ways you could use this basic class to do what you want.
One way is a "negative" search: try to match a non-alphanumeric character, and if you do, then the test fails. For this, we just add a carat at the front of the character class. This means we're matching any character not in that set.
So, the following pattern matches "any non-alphanumeric, non-underscore character." Here, a match means an invalid username:
if (preg_match('/[^A-Za-z0-9_]/', $username)) {
// invalid username
}
Or, you could do the opposite kind of match, where you give a pattern for a valid username and check if you match that. This time, we don't change the character class itself at all, but we add the + quantifier after it, meaning we're matching one or more of the "good" characters.
Additionally, we wrap the ^ and $ beginning-and-end-of-string anchors around our pattern. (It's a little confusing, but a carat at the beginning of a pattern has a completely different meaning from a carat at the beginning of a character class, within the brackets).
The end result is a pattern that means: "1 or more alphanumeric characters (plus underscore) and nothing else." A match on this one means a valid username:
if (preg_match('/^[A-Za-z0-9_]+$/', $username)) {
// valid username
}
if (preg_match("^[a-zA-Z0-9_]+$", $username) === 1) {
// Good username
}
else {
// Bad username
}
The use of the strict equality operator (===) means we're comparing what preg_match() returns to 1, the number, not the boolean value. If it returns a 0, it means there are no matches, a boolean false, an error occored. Check out the page for preg_match for more information: http://php.net/manual/en/function.preg-match.php
Per the PHP manual *preg_match* will return 0 if it can't find a successful match with your regex and FALSE if en error occurs. So if you want to make sure you're testing for 0, and not something which can evaluate to false, you should use the === operator.
If you only want letters and underscores you can use a character class of [a-z_] which specifies that the range of characters for a to z and the _ symbol will match. And the + following the class specifies that you want one or multiple of the same. The ^ says the pattern must match from the beginning of the text, while the $ says that the pattern must match up until the end of the text.
if (preg_match("/^[a-z_]+$/i", $text_variable) === 1) {
//"A match was found.";
} else {
//"A match was not found.";
}
Regex is very easy to understand if you get the basics :)
I'll try to explain to you all three expressions you tried:
With ^[a-zA-Z0-9_]*$ string will be matched which:
^ // from the beginning...
[a-zA-Z0-9_] // contains only characters a-z or A-Z or 0-9 or _ sign
* // and has 0 or more of such characters
$ // to the end
Matched strings for example:
(empty string - since you told 0 or more characters)
abc09
fidjwieofoj4fio3j4fiojrfioj3ijfo
000000000000000000000
__________
and_many_many_more_as_long_as_they_contain_alpha_characters_and___sign
With /[^a-z_-0-9]/i string will be matched which:
[^a-z_\-0-9]
// ^ means "the opposite" so that subset describes characters
// which are not included in it
// (are not a-z or _ sign, or - dash sign, or 0-9 numbers)
i modifier
// stands for case insensitive, all letters are treated as lowercase
You did not add * or ? or + after the subset so basically you are looking for one character only, and because you did not put your regexp between ^ and $ signs, this expression will finally match any text which contains at least one character which is not A-Z or a-z, or _ sign, or - dash sign, or 0-9 numbers.
Matched strings for example:
!
a>a
A<9
ffffffffff.dflskfdfd
00000,
]]]]]]]]]]]]]]]]]]
and so-on
With /^\w+$/ string will be matched which:
^ // from the beginning
\w // contains only characters a-z or A-Z or 0-9 or _ sign
+ // and the string must be at least 1 character long
$ // to the end
Probably the most useful regular expression. Remember, \w is just an alias for [a-zA-Z0-9_]. This regexp will match only whole string which is not empty and contains only alphanumeric characters and _ sign.
Matched strings for example:
mike
alice
bob10
0000000000
1111
9
php
user_example
Hope that helps. To you, most useful expression imvho to match valid usernames would be /^\w{3,15}$/ as it would match any string which is 3 to 15 characters long and consist only of alphanumeric characters and the underscore sign (a-z A-Z 0-9 _).
Try this:
<?php
function isValidUsername($username)
{
return preg_match('/^\w{3,15}$/', $username) == 1;
}
echo isValidUsername('mike999') ? 'Yes' : 'No' , '<br>';
echo isValidUsername('alice!') ? 'Yes' : 'No';
Cheers.

Regex to verify first and last character

I need to verify in php that a string should not start or end with a hyphen (-). The allowed characters are a-z, A-Z, 0-9 and a hyphen anywhere in the middle of the string.
My this regex
/^[a-zA-Z0-9-]+$/
Verifies the occurrence of allowed character expect the condition that the string should not start or end with the hyphen. How do I achieve this? I new to regex.
This should be what you need.
/^[a-z0-9]+([a-z0-9-]+[a-z0-9])?$/iD
Notice the D modifier. Without it the expression would match a string that ends in a new line. See here: http://blog.5ubliminal.com/posts/surprises-of-php-regexp-the-d-modifier/. Also, I've used the i modifier to not have to use [a-zA-Z0-9]. Keeps the expression shorter.
Here's a couple of examples. As the input string ends in a new-line, it should fail, but without the D modifier, even with the $ anchor, it passes:
// Outputs: int(1)
var_dump(preg_match('/^[a-z0-9]+([a-z0-9-]+[a-z0-9])?$/i', "aBc-d\n"));
// Outputs: int(0)
var_dump(preg_match('/^[a-z0-9]+([a-z0-9-]+[a-z0-9])?$/iD', "aBc-d\n"));
Use negative look ahead and look behind to achieve this
^(?!-)[a-zA-Z0-9-]+(?<!-)$
See it here on Regexr
^(?!-) is a negative look ahead assertion, ensures that it does not start with a dash
(?<!-)$ is a negative look behind assertion, ensures that it does not end with a dash
The advantage of the lookarounds is that they do not match a character, but just defining an assertion, that means your string can also have a length of 1, where the solution with explicitly requiring a non dash as first and last character makes a min length of 2.
Btw. a-zA-Z0-9_ is a predefined class \w so if you also want to allow the underscore you can change to:
^(?!-)[\w-]+(?<!-)$
Try this:
/^[a-zA-Z0-9_]+[a-zA-Z0-9_-]*[a-zA-Z0-9_]+$/
"One or one of anything except the hyphen, then any number of anything including hyphen, then one or more anything except the hyphen".
EDIT: This will fail if the string is one character long. Sorry about that. But you get the idea... Split it into sub-regex's.
Verifies the occurrence of allowed character expect the condition that the string should not start or end with the hyphen. How do I achieve this? I new to regex.
Put simply: ~^[^-][a-z0-9-]+[^-]$~ should match. It says the first character can not be a -, then it says the middle part can only contain [a-z0-9-], and then it says the last character can't be a '-'. That said, you can also do this with substr, I don't think you actually need a regular expression.
With substr:
<?php
$valid = ((substr($str, 0, 1) != '-') && (substr($str, -1) != '-'));
EDIT: Didn't read the alphanumeric plus hyphen part, included it in the regex.
Use the substr method.
something like:
if ((substr($str, 0, 1) != '-') && (substr($str, strlen($str)) != '-')){
It may also has a function similar to charAt in javascript but I don't remember it right now. (That will get you a more readable code)
This isn't a regular expression per-se but works according to your requirements:
if(
ctype_alnum($str[0]) &&
ctype_alnum($str[strlen($str)-1]) &&
strpos(substr($str, 1, strlen($str-1)), '-') !== false
) {
echo 'a match';
}

php regex needed to check that a string has at least one uppercase char, one lower case char and either one number or symbol

Hi I need to use php's pregmatch to check a string is valid. In order to be valid the string needs to have at least one uppercase character, at least one lowercase character, and then at least one symbol or number
thanks
You can achieve this by using lookaheads
^(?=.*[a-z])(?=.*[A-Z])(?=.*[\d,.;:]).+$
See it here on Regexr
A lookahead is a zero width assertion, that means it does not match characters, it checks from its position if the assertion stated is true. All assertions are evaluated separately, so the characters can be in any order.
^ Matches the start of the string
(?=.*[a-z]) checks if somewhere in the string is a lowercase character
(?=.*[A-Z]) checks if somewhere in the string is a uppercase character
(?=.*[\d,.;:]) checks if somewhere in the string is a digit or one of the other characters, add those you want.
.+$ Matches the string till the end of the string
As soon as one of the Assertions fail, the complete regex fail.
If the match has to be in the order you've described, you could use
$result = preg_match('/[A-Z]+[a-z]+[\d!$%^&]+/', $string);
If the characters can be in any order I'm not so sure, without doing three separate checks like so:
$result = (preg_match('/[A-Z]+/', $string) && preg_match('/[a-z]+/', $string) && preg_match('/[\d!$%^&]+/', $string));
As people have pointed out below, you can do this all in one regular expression with lookaheads.
According to your request:
[A-Z]+ Match any uppercase char
[a-z]+ Match any lowercase char
[\d§$%&]+ Match a number or special chars (add more special if you need to)
The result would look like this: [A-Z]+[a-z]+[\d§$%&]+
This isn't ideal though. You might want to check Regexr and try what kind of regex fits your requirements.
If you want these not to be necessarily in order, you need a lookahead. The following expression will validate for at least one lower char, one upper char and one number:
$result = preg_match('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])', $string);
You can put a lot of special chars with the numbers, like this:
$result = preg_match('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9$%])', $string);

Categories