skip to Main Content

I have a set of patterns and I want to check if all of them apply to at least one character in a string. The patterns I am using are: [a-z],[A-Z],[0-9] and [^a-zA-Z0-9- ]. I plan to assemble these into a basic if statement such as:

If ((pattern1,pattern2,pattern3).test(string) == true) {
    //Do Something
}

For example, if I were to use the string dA2#, it would return true since all of the patterns apply to the string, however, if I were to use the string svI2, it would return false since only 3 of the 4 patterns apply.

Please keep in mind that I am new to regex and am not fully familiar with how all of the operators work.

3

Answers


  1. Use this: (?=.*[a-z]). String multiple together like this: (?=.*[a-z])(?=.*[A-Z])

    check("a") // does not match
    check("aA") // does not match
    check("aA1") // does not match
    check("aA1&") // matches
    check("&Aa1") // matches
    
    function check (string) {
      if (/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^a-zA-Z0-9- ])/.test(string)) {
        console.log("matches", string)
      } else {
        console.log("does not match", string)
      }
    }
    Login or Signup to reply.
  2. You can do it with the function every:

    The every() method tests whether all elements in the array pass the test implemented by the provided function. It returns a Boolean value.

    Array.prototype.every()

    In our case, it will look like this:

    const patterns = [
      ".*[a-z]",
      ".*[A-Z]",
      ".*[0-9]",
      ".*[^a-zA-Z0-9- ]"
    ]
    
    const check = (source, patterns) =>
      patterns.every(pattern => new RegExp(pattern).test(source));
    
    console.log("dA2#", check("dA2#", patterns))
    console.log("svI2", check("svI2", patterns))
    console.log("aBcD123", check("aBcD123", patterns))
    console.log("&Aa1", check("&Aa1", patterns))
    Login or Signup to reply.
  3. I suggest allowing any character before and after your patterns. So that means your regex matches anything until the first of your patterns is found. Then again, any string can occur until the first match of your second pattern and so on. You can watch this in detail in this regex101 (a regex debugger that has nice explaining features).

    You can do so by adding .*. . matches any character, * enforces the beforegoing pattern to be present, zero, one or multiple times. Your pattern then looks like this:

    .*[a-z].*[A-Z].*[0-9].*[^a-zA-Z0-9- ].*
    
    const pattern = /.*[a-z].*[A-Z].*[0-9].*[^a-zA-Z0-9- ].*/;
    
    console.log("Does 'dA2#' match:", pattern.test("dA2#"));
    console.log("Does 'svI2' match:", pattern.test("svI2"));
    
    // order is important, inverted first example does not match!
    console.log("Does '#2Ad' match:", pattern.test("#2Ad"));

    Note that this assumes that you want to match the first pattern at first, the second should be the next and so on.


    Relating to @RichardHenage’s anwser

    Using (?=.*<your pattern>) to concatenate patterns does work but is not what this construct is designed for. .* simply adds any character, just as I suggested. But using (?=...) is an advanced non-standard technique. It is not necessary here and just "overpowered" and useless.

    The (?=...) construct is the so called look ahead assertion. This means that the regexp will look ahead, to the next upcoming text. The regex will only match, if the next text matches the expression in the look ahead assertion. This is useful if you want ensure that your match is at the correct position but you do not want to select it completely, e.g. when replacing.

    Example: Replace all "bar"s in all "foobar"s but not when there is no foo before.

    const pattern = /foo(?=bar)/g;
    
    const text = "bar foobar foo bar foobar foo bar";
    
    console.log("Original text:", text);
    console.log("Replaced text:", text.replace(pattern, "---"));

    So when taking a look at @RichardHenage’s answer again, the pattern matches nothing which then must be followed (=look ahead assertion) by your patterns. I think this is not what you inted to do.

    I think since you are a beginner, you should not use this answer or at least know about what it means. (?=...) is NOT how to concatenate. It works but it is way more than only concatenating.


    Relating to @aloisdg’s answer

    I personally also would not use every. This is iterating over patterns. While sometimes there is no other choice, it is possible in your case to write only one RegExp expression. And I personally think that the iteration makes your code less readable. You want to check if a string has a certain format and that is clearly visible when using one single regexp that should match a text (but I think this is personal taste). Plus using multiple expressions requires multiple compilings of the pattern to a RegExp object (which could be avoided by caching them) and multiple RegExp search executions (not avoidable).

    For more or more complicated RegExp patterns I have to admit that it is sometimes more readable to split them into multiple steps.

    Also note that the order of your patterns is not fixed in this approach.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search