I am writing a regex to handle the following but i am stuck in between

Viewed 101

Requirements:

  • There can be no capital letters in the string.
  • The string cannot contain any of the characters '^$.?*+()'
  • If '[' is present in the string it must be followed by zero or more characters other than '[' and ']', which must be followed by ']'. For example, [test] is valid, whereas [test not valid, test] and [[test]] are not valid. [test][test] is valid.
  • '|' can be used if there is words after | like ||| not valid but |test valid word| not valid

function charPos(str, char) {
     return str
         .split("")
         .map(function (c, i) { if (c == char) return i; })
         .filter(function (v) { return v >= 0; });
   }

function testString(urlPattern)
{



let regex = /[ $^*()+\[\]\\|.\/?]/g;


if(regex.test(urlPattern)){
      let secondRegex =  true;
      let thirdRegex =  true;
      let regexData = /[ $^*()+\\\\.\/?]/g;
      let regexDataNew = /[ $^*()+\\\.\/?]/g;
      if(urlPattern.indexOf("[") < urlPattern.indexOf("]") && !regexData.test(urlPattern)){
        secondRegex =  false;
      }
      if(urlPattern.indexOf("[") == -1 && urlPattern.indexOf("]") == -1){
        secondRegex =  false;
      }
      if(urlPattern.indexOf("[[") != -1 || urlPattern.indexOf("]]") != -1){
        secondRegex =  true;
      }
      let pos = charPos(urlPattern,'|');
      let largest = pos.sort((a,b)=>a-b)[pos.length - 1];
      if(largest+1 < urlPattern.length && !regexDataNew.test(urlPattern)){
        thirdRegex =  false;
      }
      if(urlPattern.indexOf("|") == -1 ){
        thirdRegex =  false;
      }
      if(secondRegex || thirdRegex){
        return 'Not Valid';
      }
      else {
        return 'Valid';
      }
     
    }
    else {
        return 'Valid1';
    }

 }
    // test case

   testString('testttthhh@@|sss'); working
   testString('testttthhh@@|'); working
   testString('testttthhh@@|[]')  working but need to show invalid.

If anyone have some solution or face same type problem help me to sort it out.

Thanks

2 Answers

You could use match any char except the chars that you don't want to match.

If you reach either a pipe or an opening square bracket, you assert either that that pipe is followed for example a word character like a-z, digits or an underscore.

In case you encounter an opening square bracket, you match it until a closing one, and assert that there is not another one following.

If an empty string should not be matched, you can start the pattern with a negative lookahead ^(?!$)

^[^\s\[\]^$.|?*+()A-Z\\]*(?:(?:\[[^\s\[\]\\]+](?!\])|\|[^\s\[\]^$.|?*+()A-Z\\]+)[^\s\[\]^$.|?*+()A-Z\\]*)*$

Explanation

  • ^ Start of string
  • [^\s\[\]^$.|?*+()A-Z\\]* Match 0+ times any char except the listed
  • (?: Non capture group
    • (?: Non capture group
      • \[[^\s\[\]\\]+](?!\]) Match from [...] not followed by ]
      • | Or
      • \|[^\s\[\]^$.|?*+()A-Z\\]+ Match a pipe and match 1+ times any listed word chars
    • ) Close non capture group
    • [^\s\[\]^$.|?*+()A-Z\\]* Match 0+ times any char except the listed
  • )* Close non capturing group and repeat 0+ times as there does not have to be a | or [] present
  • $ End of string

Regex demo

let pattern = /^[^\s\[\]^$.|?*+()A-Z\\]*(?:(?:\[[^\s\[\]\\]+](?!\])|\|[^\s\[\]^$.|?*+()A-Z\\]+)[^\s\[\]^$.|?*+()A-Z\\]*)*$/;
[
  "testttthhh@@|sss",
  "[]",
  "test test",
  "test\\test",
  "word|@pro",
  "word|%pro%",
  "testttthhh@@|",
  "testttthhh@@|[]",
  "[test]",
  "[test",
  "test]",
  "[[test]]",
  "[test][test]",
  "|||",
  "|test",
  "word|",
  "Atest"
].forEach(s => {
  console.log(pattern.test(s) + " --> " + s);
});

You can test the string with the following regular expression.

/^(?!.*\|\S*\|)(?!.*[$^.?*+()A-Z])[^\[\]\n]*(?:\[[^\[\]\n]*\][^\[\]\n]*)*[^\[\]\n]*$/

Start your engine!

Javascript's regex engine performs the following operations.

^                : match beginning of string
(?!              : begin negative lookahead
  .*\|\S*\|      : match 0+ chars followed by '|' follow by 0+
                   non-whitespace chars followed by |'
)                : end negative lookahead
(?!              : begin negative lookahead
  .*             : match 0+ chars
  [$^.?*+()A-Z]  : match a char in the char class
)                : end negative lookahead
[^\[\]\n]*       : match 0+ chars other than those char class
(?:              : begin a non-capture group
  \[             : match '['
  [^\[\]\n]*     : match 0+ chars other than those in char class
  \]             : match ']'
  [^\[\]\n]*     : match 0+ chars other than those in char class
)                : end non-capture group
*                : execute non-capture group 0+ times
[^\[\]\n]*       : match 0+ chars other than those char class
$                : match end of string
Related