I'm writing a simple quiz engine in PHP and supply the question text in this format
question|correct/feedback|wrong/feedback|wrong/feedback
There can be as many wrong/feedback options as necessary. I want to use preg_match to return the results so I can display them. For instance:
q|aaa/aaa|bbb/bbb|ccc/ccc
...should return...
array(
0 => q|aaa/aaa|bbb/bbb|ccc/ccc
1 => q
2 => aaa/aaa
3 => bbb/bbb
4 => ccc/ccc
)
So, far I've got this regular expression which matches the question and the correct/feedback combination...
([^\|]+)\|([^\/]+\/[^\|$]+)
...but I have no idea how to match the remaining wrong/feedback strings
You can also use the "glue" feature in your pattern with preg_match_all, this way it's possible to check if the syntax is correct and to extract each part at the same time.
The glue feature ensures that each match follows immediately the previous match without gap. To do that I use the A global modifier (Anchored to the start of the string or the next position after the previous match).
$s = 'q|aaa/aaa|bbb/bbb|ccc/ccc';
$pat = '~ (?!\A) \| \K [^|/]+ / [^|/]+ (?: \z (*:END) )? | \A [^|/]+ ~Ax';
if ( preg_match_all($pat, $s, $m) && isset($m['MARK']) ) {
$result = $m[0];
print_r($result);
}
I use also a marker (*:END) to be sure that the end of the string is well reached despite of the pattern constraints. If this marker exists in the matches array, it's a proof that the syntax is correct. Advantage: you have to parse the string only once (you don't even need to check the whole string syntax in a lookahead assertion anchored at the start of the string).
demo
If you want the whole question as first item in the result array, just write:
$result = array_merge([$s], $m[0]);
So, after the advice, I've decided to use preg_match to check the syntax and then explode to split the string.
This regex seems to match the string format up until any mismatch occurs.
^[^\|/]+(?:\|[^\|/]+/[^\|/]+)+
If I check that the length of the match is the same as the original string I think this will tell me the syntax is correct. Does this sound feasible?
I'm making preg_match that allows 7-10 digits.
preg_match('/[0-9]{7,10}/', $studentID
Also another preg_match code that allows maximum of 20 alphabets with space and hyphen.
preg_match ('/^[a-zA-Z -]{,20}+$/i', $familyname
Both of these are not working.
You need to add anchors to the first regex the same way you used them with the second pattern, and you must define the lower bound for the limiting quantifier in the second pattern (say, 0 to 20):
$studentID = "1234567";
if (preg_match('/^[0-9]{7,10}$/', $studentID)) {
echo "$studentID matched!\n";
}
$familyname = "Pupkin";
if (preg_match ('/^[A-Z -]{0,20}$/i', $familyname)) {
echo "$familyname matched!";
}
See the PHP demo
Note that {0,20} and its possessive {0,20}+ version will work the same here since the pattern is not followed with other consuming subpatterns (so, no need to disable backtracking for the quantified subpattern).
Also, '/^[A-Z -]{0,20}$/i' is a very generic subpattern for surnames, you might want to further precise it. E.g., to disallow strings like all spaces or ---------, you may use '/^(?=.{0,20}$)[A-Z]+(?:[ -][A-Z]+)*$/i'.
Well, I'm stuck, I cannot find the correct form for the RegEx to provide to the PHP preg_match.
I have two strings. Say "mdo" and "o", but they could be really random.
I have a dictionary of allowed chars and strings.
For the example, allowed chars are "a-gm0-9", and allowed strings are "do" and "si".
THE GOAL
I'm trying to check that the input string doesn't contain any char or string but those in the dictionary, case-insensitive.
So the case of "mdo" wouldn't match because m is allowed just like the string do. Not the same for o instead, which has o that is not an allowed char and which doesn't contain the whole allowed string do.
My struggling reason
It's ok to negate [^a-gm0-9] and (?!do|si), but what I cannot achieve is to place them inside a single regex in order to apply the following PHP code:
<?php
$inputStr = 'mdo';
$rex = '/?????/i'; // the question subject
// if disallowed chars/strings are found...
if( preg_match($regex, $inputStr) == 1 )
return false; // the $inputStr is not valid
return true;
?>
Because two cascading preg_matches would break the logic and don't work.
How to mix chars check and groups check in "AND" in a single regex? Their positions don't matter.
You can use this pattern:
return (bool) preg_match('~^(?:do|si|[a-gm0-9])*+\C~i', $inputStr);
The idea is to match all allowed chars and substrings from the start in a repeated group with a possessive quantifier and to check if a single byte \C remains. Since the quantifier is greedy and possessive, the single byte after, if found, can't be allowed.
Note that most of the time, it is more simple to negate the preg_match function, example:
return (bool) !preg_match('~^(?:do|si|[a-gm0-9])*$~iD', $inputStr);
(or with a + quantifier, if you don't want to allow empty strings)
I have the following Regex to allow alphanumeric characters and following special characters
/()-
The Regular expression is
/[^A-Za-z0-9-()-/]/
The complete method is
public function ValidateNumber($number)
{
$return = true;
$matches = null;
if((preg_match('/[^A-Za-z0-9-/()-]/', $number, $matches)) > 0)
{
$return = false;
}
return $return;
}
Above method woks fine, but also return TRUE if number has space. When i remove '/' from Regex then if number has 'space' in it then it returns FALSE.
So seems some issue with '/' in Regex.
Please advise some solution
Use this:
$theregex = '~^[a-z0-9/()-]+$~i';
if (preg_match($theregex, $yourstring)) {
// Yes! It matches!
}
else { // nah, no luck...
}
Explanation
The i flag at the end makes it case-insensitive
The ^ anchor asserts that we are at the beginning of the string
To match a hyphen in a [character class], place it at the beginning or at the end so that it is not ambiguous, since it may indicate a range, as in a-d
[a-z0-9/()-]+ matches one or more letter, digit, slash, parenthesis or hyphen
The $ anchor asserts that we are at the end of the string
Regex to allow alphanumeric characters and the the above mentioned special characters /()-,
^[A-Za-z0-9()\/-]+$
^ inside(at the strat of) chracter class means not. So your regex allows any character not of the ones mentioned inside the character class. And also it's better to escape / inside the character class and always consider in putting - at the start or end of the character class. To allow one ore more characters which was mentioned inside char class then you need to add + after the character class.
Explanation:
^ the beginning of the string
[A-Za-z0-9()\/-]+ any character of: 'A' to 'Z', 'a' to 'z',
'0' to '9', '(', ')', '\/', '-' (1 or more
times)
$ before an optional \n, and the end of the
string
You should escape / in your regex using \/
But you should probably use the following expression to do what you want:
([^A-Za-z0-9-()-\/])+
So the whole method could look like this:
public function ValidateNumber($number)
{
if (preg_match('/([^A-Za-z0-9-()-\/])+/', $number)) {
return false;
}
return true;
}
without extra variables.
In above case you try to find any characters that don't match (here ^ means characters that don't match) your criteria and if any of them is found preg_match return 1 so it means that number is invalid.
However you can also use another expression to achieve what you want - you don't find characters that don't match (as in previous example) but you check if the whole string matches your criteria using ^ as the beginning (in this case it means the beginning of the string - meaning is different that the one in previous solution) and $ as the end of the string to check the whole string. In this case your method could look like this:
public function ValidateNumber($number)
{
if (preg_match('/^([A-Za-z0-9-()-\/]+)$/', $number)) {
return true;
}
return false;
}
For Much better understanding and learning regex for the further work you can visit the below links
Learning Regular Expressions
Useful regular expression tutorial
Regular expressions tutorials
And one of the best and easy one and my favourite is
http://www.9lessons.info/2013/10/understanding-regular-expression.html?utm_source=feedburner&utm_medium=email&utm_campaign=Feed%3A+9lesson+%289lessons%29
very nice and easy tutorial for the beginners
I basically need a function to check whether a string's characters (each character) is in an array.
My code isn't working so far, but here it is anyway,
$allowedChars = array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"," ","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","0","1","2","3","4","5","6","7","8","9"," ","#",".","-","_","+"," ");
$input = "Test";
$input = str_split($input);
if (in_array($input,$allowedChars)) {echo "Yep, found.";}else {echo "Sigh, not found...";}
I want it to say 'Yep, found.' if one of the letters in $input is found in $allowedChars. Simple enough, right? Well, that doesn't work, and I haven't found a function that will search a string's individual characters for a value in an array.
By the way, I want it to be just those array's values, I'm not looking for fancy html_strip_entities or whatever it is, I want to use that exact array for the allowed characters.
You really should look into regex and the preg_match function: http://php.net/manual/en/function.preg-match.php
But, this should make your specific request work:
$allowedChars = array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"," ","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","0","1","2","3","4","5","6","7","8","9"," ","#",".","-","_","+"," ");
$input = "Test";
$input = str_split($input);
$message = "Sigh, not found...";
foreach($input as $letter) {
if (in_array($letter, $allowedChars)) {
$message = "Yep, found.";
break;
}
}
echo $message;
Are you familiar with regular expressions at all? It's sort of the more accepted way of doing what you're trying to do, unless I'm missing something here.
Take a look at preg_match(): http://php.net/manual/en/function.preg-match.php
To address your example, here's some sample code (UPDATED TO ADDRESS ISSUES IN COMMENTS):
$subject = "Hello, this is a string";
$pattern = '/[a-zA-Z0-9 #._+-]*/'; // include all the symbols you want to match here
if (preg_match($pattern, $subject))
echo "Yep, matches";
else
echo "Doesn't match :(";
A little explanation of the regex: the '^' matches the beginning of the string, the '[a-zA-Z0-9 #._+-]' part means "any character in this set", the '*' after it means "zero or more of the last thing", and finally the '$' at the end matches the end of the string.
A somewhat different approach:
$allowedChars = array("a","b","c","d","e");
$char_buff = explode('', "Test");
$foundTheseOnes = array_intersect($char_buff, $allowedChars);
if(!empty($foundTheseOnes)) {
echo 'Yep, something was found. Let\'s find out what: <br />';
print_r($foundTheseOnes);
}
Validating the characters in a string is most appropriately done with string functions.preg_match() is the most direct/elegant method for this task.
Code: (Demo)
$input="Test Test Test Test";
if(preg_match('/^[\w +.#_-]*$/',$input)){
echo "Input string does not contain any disallowed characters";
}else{
echo "Input contains one or more disallowed characters";
}
// output: Yes, input contains only allowed characters
Pattern Explanation:
/ # start pattern
^ # start matching from start of string
[\w +.#-] # match: a-z, A-Z, 0-9, underscore, space, plus, dot, atsign, hyphen
* # zero or more occurrences
$ # match until end of string
/ # end pattern
Significant points:
The ^ and $ anchors are crucial to ensure that the entire string is validated versus just a substring of the string.
The \w (a.k.a. "any word character" -> a shorthand character class) is the easy way to write: [a-zA-Z0-9_]
The . dot character loses its "match anything (almost)" meaning and becomes literal when it is written inside of a character class. No escaping slash is necessary.
The hyphen inside of a character class can be written without an escaping slash (\-) so long as the it is positioned at the start or end of the character class. If the hyphen is not at the start/end and it is not escaped, it will create a range of characters between the characters on either side of it.Like it or not, [.-z] will not match a hyphen symbol because it does not exist "between" the dot character and the lowercase letter z on the ascii table.
The * that follows the character class is the "quantifier". The asterisk means "0 or more" of the preceding character class. In this case, this means that preg_match() will allow an empty string. If you want to deny an empty string, you can use + which means "1 or more" of the preceding character class. Finally, you can be far more specific about string length by using a number or numbers in a curly bracketed expression.
{8} would mean the string must be exactly 8 characters long.
{4,} would mean the string must be at least 4 characters long.
{,10} would mean the string length must be between 0 and 10.
{5,9} would mean the string length must be between 5 and 9 characters.
All of that advice aside, if you absolutely must use your array of characters AND you wanted to use a loop to check individual characters against your validation array (and I certainly don't recommend it), then the goal should be to reduce the number of array elements involved so as to reduce total iterations.
Your $allowedChars array has multiple elements that contain the space character, but only one is necessary. You should prepare the array using array_unique() or a similar technique.
str_split($input) will run the chance of generating an array with duplicate elements. For example, if $input="Test Test Test Test"; then the resultant array from str_split() will have 19 elements, 14 of which will require redundant validation checks.
You could probably eliminate redundancies from str_split() by calling count_chars($input,3) and feeding that to str_split() or alternatively you could call str_split() then array_unique() before performing the iterative process.
Because you're just validating a string, see preg_match() and other PCRE functions for handling this instead.
Alternatively, you can use strcspn() to do...
$check = "abcde.... '; // fill in the rest of the characters
$test = "Test";
echo ((strcspn($test, $check) === strlen($test)) ? "Sigh, not found..." : 'Yep, found.');