Best preg_match expression for international name - php

I'm trying to find a good preg_match expression that allow all letters (included accented letters), the space , and these symbols: - '
I thought this could be a good solution '/^\p{L}+$/ui', but I can't find a successful way to add the symbols I need, if that is possible...
Otherwise I guess I should use something like this:
'#^[a-zA-Z0-9àòäöüÄÖÜ \.\]]+$#'
but there are so many accents that I was hoping to find a better solution.

Try placing the \p{L} and allowed symbols inside brackets:
$name = "B-jör n'Bòrg";
if (preg_match("/^[- '\p{L}]+$/u", $name)) {
echo "$name is a valid name!"; // It is
}
You may also want to add some additional checks, e.g. to make sure that names starts and ends with a letter and not a symbol.
Edit
This will make sure that names starts/ends with a letter and does not contain consecutive symbols:
$name = "-Björ n''Bòrg-";
if (preg_match("/^\p{L}([- ']\p{L}|\p{L})*$/u", $name)) {
echo "$name is a valid name!"; // It's not
}

Related

Regex for Chinese / Japanese letters

Okai so I already have this regular expression for names allowed on my website.
However, I also wish to add other possible letters that names use.
Does someone have a good regex or know how I can make this more complete? I have searched for quite a while now, and I can't find anything that suits my needs.
This is my current regex for checking names:
$regex = "/^([a-zA-ZàáâäãåąčćęèéêëėįìíîïłńòóôöõøùúûüųūÿýżźñçčšžÀÁÂÄÃÅĄĆČĖĘÈÉÊËÌÍÎÏĮŁŃÒÓÔÖÕØÙÚÛÜŲŪŸÝŻŹÑßÇŒÆČŠŽ∂ð ,.'-])+$/";
if(preg_match($regex, $fullname)){
// do something
}
As Lucas Trzesniewski has mentioned, the \p{L} will include the [a-zA-Z], so I have removed from the pattern.
Thus, combining the character lists that you have included in the example; the pattern will look like this, /^[\p{L}\s,.'-]+$/u
^[]+$ matches the string from start to end, thus + also imply the need of matching one or more
\p{L} matches unicode characters
\s,.'- matches space, comma, period, single quotation, and dash
u the PCRE_UTF8 modifier, this modifier turns on additional functionality of PCRE that is incompatible with Perl.
if(preg_match("/^[\p{L}\s,.'-]+$/u", "お元気ですか你好吗how are you你好嗎,.'-") === 1) {
echo "match";
}
else {
echo "no match";
}
// match
if(preg_match("/^[\p{L}\s,.'-]+$/u", "お元気ですか你好吗how are you你好_嗎-,.'") === 1) {
echo "match";
}
else {
echo "no match";
}
// no match as there are underscore in 你好_嗎

PHP preg_match only letters and no numbers, maybe an explanation

I have this email regex, and i would like to make same thing with a name regex, so you can't write numbers in a name, how should i change it?
if (!preg_match("/^[[:alnum:]][a-z0-9_.-]*#[a-z0-9.-]+\.[a-z]{2,4}$/i", trim($_POST['email']))) {
$emailError = 'You entered an invalid email address.';
$hasError = true;
}
I know that [a-z0-9_.-] means that a-z 0-9 and _ . - is usable.
But i want to only use a-z and this is why my brain is breaking across, as i don't understand the whole sentence, could anyone "translate" it to only use a-z and no numbers neither _ - .?
I would like it to be changed to a name regex, so people can't write numbers in their name.
I understand that i can write
if (!preg_match("/^[[:alnum:]][a-z]*#[a-z]+\.[a-z]{2,4}$/i", trim($_POST['name']))) {
$nameError = 'You entered invalid characters in your name.';
$hasError = true;
}
but for me it doesn't make any sense, how i should enter that into the regex above.
but i could also type in this? so i say if it contains 0-9 then its invalid? but i don't know what it means all these characters in the sentence.
if (preg_match("/^[[:alnum:]][0-9]*#[0-9]+\.[0-9]{2,4}$/i", trim($_POST['name']))) {
$nameError = 'You entered invalid characters in your name.';
$hasError = true;
}
I tried to research about "preg_match" but i can't find an explanation, so i can make my a regex for "preg_match" on my own
You could try the below.
/^[a-z]+#[a-z]+\.[a-z]{2,4}$/i
[[:alnum:]] Matches both alphabets and numbers but POSIX [[:alpha:]] matches only the alphabets.
[a-z]* zero or more lowercase letters. [a-z]+ one or more lowercase letters.
i modifier helps to do a case insensitive match.
If you want to understand the regex pattern try using http://regex101.com . That will let you analyze each part of the pattern.
You can try using this, it should do the job:
/^[[:alpha:]][a-z]*#[a-z]+\.[a-z]{2,4}$/i
But the simpler regex for a name check that I use and haven't had any issues with is:
/^([a-z])+$/i
Although the first one may be better (?) the second one makes the regex slightly more understandable in my opinion.

Accented character validation in PHP

What is a good one-liner php regex for checking first/last name fields with accented characters (in case someone's name was Pièrre), that could match something like:
<?php
$strErrorMessage = null;
if(!preg_match('/\p{L}0-9\s-+/u', trim($_POST["firstname"])))
$strErrorMessage = "Your first name can only contain valid characters, ".
"spaces, minus signs, or numbers.";
?>
This tries to use unicode verification, from this post, but doesn't work correctly. The solution seems pretty hard to google.
Aside from the difficulty to validate a name, you need to put your characters into a character class. /\p{L}0-9\s-+/u matches only on a sequence like "Ä0-9 ------". What you wanted to do is
/^[\p{L}0-9\s-]+$/u
Additionally I added anchors, they ensure that the regex tries to match the complete string.
As ex3v mentioned you should probably add \p{M} to that class to match also combination characters. See Unicode properties.
/^[\p{L}\p{M}0-9\s-]+$/u

Check if variable contains text or numbers

Im creating a search function. The users are only allowed to use a-z A-Z and 0-9. How do i check if $var only contains text or numbers, and not special characters ?
I have tried something like this:
if (!preg_match('/[^a-z]/i', $search) {
$error = "error...";
}
If anyone have a smarter solution, please let me know. It could also be something checking for special characters.
You're pretty much there. Just add numbers 0-9 to your regular expression, like this:
if(preg_match('/[^a-z0-9]/i', $search))
{
$error = "Error...";
}
The /i flag tells the expression to ignore case, so A-Z is not needed inside the letter list.
In your original code, you were looking for anything that wasn't a letter or number, while also checking to see if preg_match() hadn't matched anything - you created a double negative. The code above executes the if() if anything that isn't a letter or number is found. Full credit to #brain in the comments.
To allow other characters, simply add them to the characters inside the braces:
if(preg_match('/[^a-z0-9 \.]/i', $search))
{
$error = "Error...";
}
This example allows spaces and . (dots).
Something like this:
if(!preg_match('/^[a-zA-Z0-9]+$/', $search)) {
// error
}

A solid nickname regexp

I want a regular expression to validate a nickname: 6 to 36 characters, it should contain at least one letter. Other allowed characters: 0-9 and underscores.
This is what I have now:
if(!preg_match('/^.*(?=\d{0,})(?=[a-zA-Z]{1,})(?=[a-zA-Z0-9_]{6,36}).*$/i', $value)){
echo 'bad';
}
else{
echo 'good';
}
This seems to work, but when a validate this strings for example:
11111111111a > is not valid, but it should
aaaaaaa!aaaa > is valid, but it shouldn't
Any ideas to make this regexp better?
I would actually split your task into two regex:
to find out whether it's a valid word: /^\w{6,36}$/i
to find out whether it contains a letter /[a-z]/i
I think it's much simpler this way.
Try this:
'/^(?=.*[a-z])\w{6,36}$/i'
Here are some of the problems with your original regex:
/^.*(?=\d{0,})(?=[a-zA-Z]{1,})(?=[a-zA-Z0-9_]{6,36}).*$/i
(?=\d{0,}): What is this for??? This is always true and doesn't do anything!
(?=[a-zA-Z]{1,}): You don't need the {1,} part, you just need to find one letter, and i flag also allows you to omit A-Z
/^.*: You're matching these outside of the lookaround; it should be inside
(?=[a-zA-Z0-9_]{6,36}).*$: this means that as long as there are between 6-36 \w characters, everything else in the rest of the string matches! The string can be 100 characters long mostly containing illegal characters and it will still match!
You can do it easily using two calls to preg_match as:
if( preg_match('/^[a-z0-9_]{6,36}$/i',$input) && preg_match('/[a-z]/i',$input)) {
// good
} else {
// bad
}

Categories