Link to home
Start Free TrialLog in
Avatar of Michel Plungjan
Michel PlungjanFlag for Denmark

asked on

Regular expression needed

I have a form field. In this field you may no enter something that will result in a search for the letters FG on their own
Anything letter or digit in front or any letter or digit after FG is fine

Valid queries:

AFG
AFG01
FGA
FGA01
FG1
FG1 OR FG2

The current regexp is this:

^FG$|[ ]FG$|[ ]FG[ ]

However in this I am able to search using
(AB OR FG)
and also ((((FG XXX)))
which I need to be not allowed.

Thanks

Michel
Avatar of stefan73
stefan73
Flag of Germany image

Hi mplungjan,
What about
^\w*FG\w*$

(Assuming you want any number of letter/digit before FG)

Enjoy,

Stefan
Avatar of Michel Plungjan

ASKER

Here is my test script.

Seems your regexp is not complete
<script>
reg = /^\w*FG\w*$/
function testReg(str,valid) {
  v = (valid)?"Valid:":"Not Valid"
  test = reg.test(str);
  p = ((test && valid) || (!test && !valid))?"passed":"not passed"
  txt = "<hr>"+v+" |"+str+"| "+p+ " ("+test+")"
  document.write(txt)
}

testReg('FG',0)
testReg(' FG',0)
testReg('(AB OR FG)',0)
testReg('(AB OR FG0)',1)
testReg('FG0',1)
testReg('AFGB',1)
testReg(' FG0',1)

</script>

I get

Not Valid |FG| not passed (true) <<<<<<<
Not Valid | FG| passed (false)
Not Valid |(AB OR FG)| passed (false)
Valid: |(AB OR FG0)| not passed (false) <<<<<<<
Valid: |FG0| passed (true)
Valid: |AFGB| passed (true)
Valid: | FG0| not passed (false) <<<<<<<<
Avatar of NorCal2612
NorCal2612

Would this work?

#!/usr/bin/perl

$in = shift;

if ($in =~ /(\d|\w)FG(\d|\w)/ig) { print "OK\n"; } else { print "Not OK\n"; }

# end script

Good luck! :D
Please plug it into my test page and see it does not work:

Not Valid |FG| passed (false)
--------------------------------------------------------------------------------
Not Valid | FG| passed (false)
--------------------------------------------------------------------------------
Not Valid |(AB OR FG)| passed (false)
--------------------------------------------------------------------------------
Valid: |(AB OR FG0)| not passed (false) <<<<
--------------------------------------------------------------------------------
Valid: |FG0| not passed (false) <<<<<<<<<
--------------------------------------------------------------------------------
Valid: |AFGB| passed (true)
--------------------------------------------------------------------------------
Valid: | FG0| not passed (false)  <<<<<<<
Ok sorry I misread your initial requirements slightly. This worked for me in all cases:

#!/usr/bin/perl

$in = shift;

if ($in =~ /(\d|\w)FG/ig || $in =~ /FG(\d|\w)/ig) { print "OK\n"; } else { print "Not OK\n"; }
mplungjan,

I'm not quite sure for which cases you need a match and which must explicitly fail... ...,0 must succeed, ,1 must fail?

> testReg('FG',0)
> testReg(' FG',0)
> testReg('(AB OR FG)',0)
> testReg('(AB OR FG0)',1)
> testReg('FG0',1)
> testReg('AFGB',1)
> testReg(' FG0',1)



Stefan
Here is a version with my latest suggestion - please note it is a NEGATIVE test - my test does not pass all examples

<script>
//reg = /^\w*FG\w*$/; // positive test
//reg = /(\d|\w)FG(\d|\w)/ig; // positive test
reg = /^FG$|[ ]FG[ ]|FG[^a-z0-9]/; // negative test

function testReg(str,valid) {
  v = (valid)?"Valid:":"Not Valid"
  test = reg.test(str);
//  p = ((test && valid) || (!test && !valid))?"passed":"not passed"; // positive test
  p = ((test && !valid) || (!test && valid))?"passed":"not passed"; // negative test
  txt = "<hr>"+v+" |"+str+"| "+p+ " ("+test+")"
  document.write(txt)
}

testReg('FG',0); // not valid
testReg(' FG',0); // not valid
testReg(' FG ',0); // not valid
testReg('(AB OR FG)',0); // not valid
testReg('(AB OR FG0)',1); // valid
testReg('FG0',1); // valid
testReg('AFGB',1); // valid
testReg(' FG0',1); // valid

</script>
ALmost

<script>
//reg = /^\w*FG\w*$/; // positive test
//reg = /(\d|\w)FG(\d|\w)/ig; // positive test
reg = /^FG$|[ ]FG[ ]|^FG[ ]|^[ ]FG$|FG[^a-z0-9]/; // negative test

function testReg(str,valid) {
  v = (valid)?"Valid:":"Not Valid"
  test = reg.test(str);
//  p = ((test && valid) || (!test && !valid))?"passed":"not passed"; // positive test
  p = ((test && !valid) || (!test && valid))?"passed":"not passed"; // negative test
  txt = "<hr>"+v+" |"+str+"| "+p+ " ("+test+")"
  document.write(txt)
}

testReg('FG',0)
testReg(' FG',0)
testReg(' FG ',0)
testReg('(AB OR FG)',0)
testReg('(AB OR FG0)',1)
testReg('FG0',1)
testReg('AFGB',1); <<<<<<< does not pass !!!
testReg(' FG0',1)

</script>
This doesn't look quite like perl code....  So i tested it using perl, and every one passed:

#NOTE: If it matches this pattern, it is NOT valid
if(  /\bFG\b/  ){
    print "NOT VALID";
}
else {
    print "Valid";
}


Here is the perl code:
#!/usr/bin/perl
use strict;

sub testReg {
      my ($str, $valid) = @_;
      my $v = ($valid)?"    Valid":"Not Valid";
      my $test = ($str =~ /\bFG\b/);
      my $p = ((!$test && $valid) || ($test && !$valid))?"    passed":"not passed";
      print "$v: $p: $str\n";
}

testReg('FG',0);
testReg(' FG',0);
testReg(' FG ',0);
testReg('(AB OR FG)',0);
testReg('(AB OR FG0)',1);
testReg('FG0',1);
testReg('AFGB',1);
testReg(' FG0',1);
Try it this way:

#!/usr/bin/perl -w
use strict;

while (<DATA>) {
    if (/^FG$|(?<=[\s"'(])FG(?=[\s'")])/) {
        chomp;
        print "$_ not allowed\n";
    }
}
__DATA__
FG
AFG
AFG01
FGA
FGA01
FG1
FG1 OR FG2
(FG OR AB)
(AB OR FG)
(AB OR FG0)
"FG"
(FG)
'FG'

The output is:

FG not allowed
(FG OR AB) not allowed
(AB OR FG) not allowed
"FG" not allowed
(FG) not allowed
'FG' not allowed

all other lines are allowed.  I assumed you would like to disallow 'FG' and "FG", if this is an incorrect assumption, you can remove the ' and the " from the character classes used by the lookbehid and lookahead assertions.

Will this do what you need?
Actually, you could tighten that up a bit further by using:

#!/usr/bin/perl -w
use strict;

while (<DATA>) {
    if (/^\s*FG\s*$|(?<=[\s"'(])FG(?=[\s'")])/) {
        chomp;
        print "$_ not allowed\n";
    }
}
__DATA__
FG
AFG
AFG01
FGA
FGA01
FG1
FG1 OR FG2
(FG OR AB)
(AB OR FG)
(AB OR FG0)
"FG"
(FG)
'FG'
 FG
FG
 FG
'FG)

instead.  Changing it to ^\s*FG\s*$ will disallow FG preceded or followed by nothing but spaces (either <space>FG, FG<space>, and <space>FG<space>, if on a line by themselves, will also be disallowed).
while( <DATA> ){
    if( /(?<!\w)FG(?!\w)/ ){
        chomp;
        print "$_ not allowed\n";
    }
}
__DATA__
AFG
AFG01
FGA
FGA01
FG1
FG1 OR FG2
(FG OR AB)
(AB OR FG)
(AB OR FG0)
"FG"
(FG)
'FG'
 FG
FG
 FG
'FG)
/^\s*FG\s*$|(?<=[\s"'(])FG(?=[\s'")])/
fails on
FG A
It is not perl because I did not ask for perl. Just a regexp. So please no perl or chomp
I am not using perl but a java parser - the regex experts sit here and most regexps out there are perl 5 compliant.

thanks for any help

Michel
/(?<!\w)FG(?!\w)/
ASKER CERTIFIED SOLUTION
Avatar of Adam314
Adam314

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Chomp is not necessary for the regular expression I provided, it's just in a script that tests the regex, which is (/^\s*FG\s*$|(?<=[\s"'(])FG(?=[\s'")])/).

Does (/^\s*FG\s*$|(?<=[\s"'(])FG(?=[\s'")])/) work for you?
oops -- remove the parentheses left over from the "if" statement...

Does /^\s*FG\s*$|(?<=[\s"'(])FG(?=[\s'")])/ work for you?
Seems Adam has the lead so far.
https://www.experts-exchange.com/questions/21901845/Regular-expression-needed.html#17001773

seems to work perfectly. I will run it through some more tests but that is very promising
Thanks all.

Very simple and effective solution

Michel