Reputation: 7056
I'm trying to modify this regex pattern so that it disallows two specified characters in a row or at the start/end -
/^[^\!\"\£\$\%\^\&\*\(\)\[\]\{\}\@\~\#\/\>\<\\\*]+$/
So at the moment it prevents these characters anywhere in the string, but I also want to stop the following from happening with these characters:
any spaces, apostophes '
, underscores _
or hyphens -
or dots .
appearing at the start of end of the string
also prevent any two of these characters in a row, i.e. ''
or _._
or ' -__- ' .
Any help would be hugely appreciated.
Thanks a lot
Upvotes: 0
Views: 2439
Reputation: 5037
I'm not sure I understand the exact problem, but here's a suggestion:
<?php
$test = "__-Remove '' _._ or -__- but not foo bar '. _ \n";
$expected = 'Remove or but not foo bar';
// The list of disallowed characters. There is no need to escape.
// This will be done with the function preg_quote.
$excluded_of_bounds = "'_.-";
// Remove disallowed characters from start/end of the string.
// We add the space characters that should not be in the regexp.
$test = trim($test, $excluded_of_bounds . " \r\n");
// In two passes
$patterns = array(
// 1/ We remove all successive disallowed characters,
// excepted for the spaces
'#[' . preg_quote($excluded_of_bounds) . ']{2,}#',
// 2/ We replace the successive spaces by a unique space.
'#\s{2,}#',
);
$remplacements = array('', ' ');
// Go!
$test = preg_replace($patterns, $remplacements, $test);
// bool(true)
var_dump($expected === $test);
Upvotes: 0
Reputation: 6896
$tests[1] = "fail_.fail"; // doubles
$tests[] = "fail_-fail";
$tests[] = "fail_ fail";
$tests[] = "fail fail";
$tests[] = "fail -fail";
$tests[] = "pas.s_1";
$tests[] = "pa.s-s_2"; // singles
$tests[] = "pas.s_3";
$tests[] = "p.a.s.s_4";
$tests[10] = "pa s-s_5";
$tests[] = "fail fail'"; // pre or post-pended
$tests[] = " fail fail";
$tests[] = " fail fail";
$tests[] = "fail fail_";
$tests[15] = "fail fail-";
// The list of disallowed characters. There is no need to escape.
// This will be done with the function preg_quote.
$exclude = array(" ","'", "_", ".", "-");
$pattern = "#[" . preg_quote(join("", $exclude)) . "]{2,}#s";
// run through the simple test cases
foreach($tests as $k=>$test){
if(
in_array(substr($test, 0, 1), $exclude)
|| in_array(substr(strrev($test), 0 , 1) , $exclude))
{
echo "$k thats a fail" . PHP_EOL;
continue;
}
$test = preg_match( $pattern, $test);
if($test === 1){
echo "$k - thats a fail". PHP_EOL ;
}else{
echo "$k - thats a pass $test ". PHP_EOL ;
}
}
Stealing hopelessly from other replies, I'd advocate using PHPs simple in_array to check the start and end of the string first and just fail early on discovering something bad.
If the test gets past that, then run a really simple regex.
Stick the lot into a function and return false on failure -- that would rm quite a few verbose lines I added -- you could even send in the exclusion array as a variable -- but it would seem rather a specific function so may be YAGNI
eg
if( badString($exclude_array, $input) ) // do stuff
Upvotes: 0
Reputation: 13631
One way
/^(?=[^!"£$%^&*()[\]{}@~#\/><\\*]+$)(?!.*[ '_.-]{2})[^ '_.-].*[^ '_.-]$/
Note, only tested as javascript regex, i.e.
var rex = /^(?=[^!"£$%^&*()[\]{}@~#\/><\\*]+$)(?!.*[ '_.-]{2})[^ '_.-].*[^ '_.-]$/;
rex.test('okay'); // true
rex.test('_not okay'); // false
Or, to match on disallowed patterns
/^[ '_.-]|[ '_.-]$|[!"£$%^&*()[\]{}@~#\/><\\*]|[ '_.-]{2}/
The first regex will only match strings that contain no disallowed patterns.
The one above will match any disallowed patterns in a string.
Update
Now tested briefly using php. The only difference is that the "
in the character set needed to be escaped.
<?php
$test = 'some string';
$regex = "/^[ '_.-]|[ '_.-]$|[!\"£$%^&*()[\]{}@~#\/><\\*]|[ '_.-]{2}/";
if ( preg_match( $regex, $test ) ) {
echo 'Disallowed!';
}
Upvotes: 1