Hello i have a regex which accepts mostly every character including specials.And i have set
it to accept minimum 8 and maximum 30 characters.
Everything is right for minimum but it's not working for maximum.
If string is more than 30 or any length. The result is true.
The pattern is here:
$pattern = '/[A-Za-z0-9' . preg_quote( '.%^&()$##!/-+/', '/') . ']{8,30}/';
The whole testing code is:
$pattern = '/^[A-Za-z0-9' . preg_quote( '.%^&()$##!/-+/', '/') . ']{8,30}$/';
if(preg_match($pattern, $pass))
{
echo '<br>true';
}
else
{
echo '<br>false';
}
?>
This will match any string up to 30 characters within the string. You need to include the start and end of the string:
$pattern = '/^[A-Za-z0-9' . preg_quote( '.%^&()$##!/-+/', '/') . ']{8,30}$/';
The first $pattern expression in your question is missing the required: ^ and $ beginning and end of line assertions - (but the example code snippet which follows uses them correctly.)
You also need to escape the dash/hyphen inside the character class - the hyphen defines a range of characters. (Note that the forward slash / is NOT the escape char!) Try this:
$pattern = '/^[A-Za-z0-9.%^&()$##!\-+\/]{8,30}$/';
Related
I am trying to replace 2.0 to stack,
but the following code replace 2008 to 2.08
Following is my code:
$string = 'The story is inspired by the Operation Batla House that took place in 2008 ';
$tag = '2.0';
$pattern = '/(\s|^)'.($tag).'(?=[^a-z^A-Z])/i';
echo preg_replace($pattern, '2.0', $string);
Use preg_quote and make sure you pass the regex delimiter as the second argument:
$string = 'The story is inspired by the Operation Batla House that took place in 2008 ';
$tag = '2.0';
$pattern = '/(\s|^)' . preg_quote($tag, '/') . '(?=[^a-zA-Z])/i';
// ^^^^^^^^^^^^^^^^^^^^^
echo preg_replace($pattern, '2.0', $string);
The string is not modified. See the PHP demo. The regex delimiter here is /, thus it is passed as the 2nd parameter to preg_quote.
Note that [^a-z^A-Z] matches any chars but ASCII letters and ^ since you added the second ^ in the character class. I changed [^a-z^A-Z] to [^a-zA-Z].
Also, the capturing group at the start may be replaced with a single lookbehind, (?<!\S), it will make sure your match occurs only at the string start or after a whitespace.
If you expect to also match at the end of the string, replace (?=[^a-zA-Z]) (that requires a char other than a letter immediately to the right of the current location) with (?![a-zA-Z]) (that requires a char other than a letter or end of string immediately to the right of the current location).
So, use
$pattern = '/(?<!\S)' . preg_quote($tag, '/') . '(?![a-zA-Z])/i';
Also, consider using unambiguous word boundaries
$pattern = '/(?<!\w)' . preg_quote($tag, '/') . '(?!\w)/i';
I have a generic routine which used to substitute out short-codes (which begin with a "^" character) with gender specific options. I have been asked to extend this to correct some common misspellings. These words won't have a special character at the start.
Until now I have been using PHP's str_replace function but because of the possibility of some words appearing within others, I need to ensure that the code uses word boundaries when matching. I am now attempting to use preg_replace.
While the actual code is getting data from a database table, including the gender specific replacements, I can reproduce the issue with simpler code for the purposes of asking this question.
Consider the following array with $search => $replace structure:
$subs = array("^Heshe" => "He",
"apples" => "bananas");
I then want to cycle through the array to replace the tokens:
$message = "^Heshe likes apples but not crabapples.";
foreach ($subs as $search => $replace)
{
$pattern = '/\b' . preg_quote($search, '/') . '\b/u';
$message = preg_replace($pattern, $replace, $message);
}
echo $message;
I expect the message He likes bananas but not crabapples. to be displayed, but instead I get the message ^Heshe likes bananas but not crabapples.
I have also tried $pattern = '/\b\Q' . $search . '\E\b/u', also with the same results.
Unfortunately, the "^" characters are part of some legacy system and changing it is not feasible. How do I get the regex to work?
Problem is this line:
$pattern = '/\b' . preg_quote($search, '/') . '\b/u';
As $search is ^Heshe you cannot match \b (word boundary) before ^ since that is not a word character.
You can use lookarounds instead in your pattern like this:
$pattern = '/(?<!\w)' . preg_quote($search, '/') . '(?!\w)/u';
Which means match $search if it is not followed and preceded by a word char.
Or else use:
$pattern = '/(?<=\s|^)' . preg_quote($search, '/') . '(?=\s|$)/u';
Which means match $search if it is followed and preceded by a whitespace or line start/end.
Please forgive me if this question appears too cheap.
I have this line:
preg_match_all($pattern, $_GET['id'], $arr);
When you pass a value with space during a search, the value breaks once a space is encountered.
For instance:
36 2543541284
Notice a space between 6 and 2. In a situation similar to this, only 36 is displayed.
The reminder of digits after space are ignored. This is giving users, "no data found" message.
I have tried using urlencode to add 20% but no luck.
preg_match_all($pattern, rawurlencode($_GET[id]), $arr);
I have also tried urlencode but to no avail.
What am I possibly doing wrong?
function format($matches)
{
return $matches[1][0].(strlen($matches[2][0])>0?$matches[2][0]:" ").$matches[3][0].(strlen($matches[4][0])>0?" ".$matches[4][0]:"");
}
// CONSTRUCT A REGULAR EXPRESSION
$pattern
= '/' // regex delimiter
. '(' // START of a capture group
. '\d{2}' // exactly two digits
. ')' // END of capture group
. '(' // START SECOND capture group
. '[ND]?' // letters "D" OR "N" in any order or number - This is optional
. ')' // END SECOND capture group
. '(' // START THIRD capture group
. '\d*' // any number of digits
. ')' // END THIRD capture group
. '(' // START FOURTH capture group
. 'GG' // the letters "GG" EXACTLY
. '[\d]*' // any number of digits
. ')' // END THIRD capture group
. '?' // make the LAST capture group OPTIONAL
. '/' // regex delimiter
;
preg_match_all($pattern, rawurlencode($_GET[id]), $arr);
// REFORMAT the array
$str = format($arr);
// show what we did to the data
echo '<pre>' . PHP_EOL;
echo '1...5...10...15...20...' . PHP_EOL;
echo $pattern;
echo PHP_EOL;
//Are we getting what we asked for? This is a test. We will comment out all 6 lines if we are happy with output of our REFORMATTING.
echo $str;
echo PHP_EOL;
Your regex as it stands will not match two digits followed by a space and further digits.
If you want it to, you could change [ND]? to [\sND]?, although this would also allow a space if the string wasn't all digits.
You need to specify the rules precisely if you want further advice on the regex.
Regex is an overkill in this case.
From the urlencode manual:
Returns a string in which all non-alphanumeric characters except -_.
have been replaced with a percent (%) sign followed by two hex digits
and spaces encoded as plus (+) signs. It is encoded the same way that
the posted data from a WWW form is encoded, that is the same way as in
application/x-www-form-urlencoded media type. This differs from the »
RFC 3986 encoding (see rawurlencode()) in that for historical reasons,
spaces are encoded as plus (+) signs.
It clearly states that if you want spaces to be encoded as %20, and not +, you should use rawurlencode().
Code example:
$strings = array(
'36 2543541284',
'1234 5678',
'this is a string'
);
$strings_encoded = array();
foreach($strings as $string)
{
$strings_encoded[] = rawurlencode($string);
}
var_dump($strings_encoded);
Outputs:
array(3) {
[0]=>
string(15) "36%202543541284"
[1]=>
string(11) "1234%205678"
[2]=>
string(22) "this%20is%20a%20string"
}
I am using PHP to find out whether a string, which starts with a special regular expression character, occurs as a word in a text string. This is the PHP code:
$subject = " hello [hello [helloagain ";
$pattern = preg_quote("[hello");
if (preg_match("/\b" . $pattern . "\b/", $subject, $dummy)) {
echo "match";
} else {
echo "no match";
}
The pattern starts with character [, hence, preg_quote() is used to escape it. There is an instance of [hello as a word in the subject so there should be one match, but the above preg_match() returns no match. I think the reason is that in the subject a special character is not recognized as the start or end of a word, but I can’t think of any way round this, any ideas? Thank you.
If I understand the question correctly, you could just use strpos() with a leading space to separate words:
$subject = " hello [hello [helloagain ";
$pattern = " [hello";
if(strpos($subject, $pattern) !== FALSE)
// ...
else
// ...
I think that not using reg-ex here is actually a better method since you are looking for special reg-ex chars, and they do not have to be escaped if you use strpos().
It would take some modification to be right in all cases, but this worked when I tried it.
You are correct that a word boundary will not match between a space and a [ symbol.
Instead of using a word boundary you can explicitly search for spaces (and other separators such as commas and periods if you wish) before and after the word:
if (preg_match("/(\s|^)" . $pattern . "(?=\s|$)/", $subject, $dummy)) {
I am trying to make sense of handling regular expression with php. So far my code is:
PHP code:
$string = "This is a 1 2 3 test.";
$pattern = '/^[a-zA-Z0-9\. ]$/';
$match = preg_match($pattern, $string);
echo "string: " . $string . " regex response: " , $match;
Why is $match always returning 0 when I think it should be returning a 1?
[a-zA-Z0-9\. ] means one character which is alphanumeric or "." or " ". You will want to repeat this pattern:
$pattern = '/^[a-zA-Z0-9. ]+$/';
^
"one or more"
Note: you don't need to escape . inside a character group.
Here's what you're pattern is saying:
'/: Start the expressions
^: Beginning of the string
[a-zA-Z0-9\. ]: Any one alphanumeric character, period or space (you should actually be using \s for spaces if your intention is to match any whitespace character).
$: End of the string
/': End the expression
So, an example of a string that would yield a match result is:
$string = 'a'
Of other note, if you're actually trying to get the matches from the result, you'll want to use the third parameter of preg_match:
$numResults = preg_match($pattern, $string, $matches);
You need a quantifier on the end of your character class, such as +, which means match 1 or more times.
Ideone.