Joseph
Joseph

Reputation: 119827

Matching a substring that doesn't contain a certain substring

// Pattern
{{\s*.*?(?!contact\.firstName|contact\.lastName|contact\.phoneNumber|contact\.language)\s*}}

// String
test {{debug}} {{contact.language}} test {{another}}

I'm trying to match substrings that are between {{ }} that are not in a certain set of strings (contact.firstName, contact.lastName, contact.phoneNumber, contact.language). Now in this example, it so happens that the text I wanted to exclude all have contact.. But no, it could be any text, and may contain symbols and spaces.

In this example, I need to match {{debug}} and {{another}}. If I understand the regex correctly, it should match anything (even blank) other than those listed under (?! ). However, it keeps matching {{contact.language}} possibly due to the .* part.

How does one match anything other than those defined in the set? I'm not particularly adept in regex, as I don't really use it on an everyday basis.

Upvotes: 1

Views: 99

Answers (3)

Jan
Jan

Reputation: 5815

I believe you're trying to do something like this:

{{((?!contact\.firstName|contact\.lastName|contact\.phoneNumber|contact\.language)[^{}])*}}

from Regular expression to match a line that doesn't contain a word?

DEMO: https://regex101.com/r/wT6zB0/3

EDIT: Updated so it doesn't match across brackets

Upvotes: 0

user557597
user557597

Reputation:

If you need to use assertions to exclude those strings, this should work.

# /\{\{(?!\s*contact\.(?:firstName|lastName|phoneNumber|language)\s*\}\})(?:(?!\{\{|\}\})[\S\s])+\}\}/


 \{\{                     # Opening brace '{{'
 (?!                      # Assert, not any of these after open/close braces
      \s* 
      contact\.
      (?:
           firstName
        |  lastName
        |  phoneNumber
        |  language
      )
      \s* 
      \}\}
 )
 (?:                      # Cluster
      (?! \{\{ | \}\} )        # Assert not open/close braces
      [\S\s]                   # Grab a single character
 )+                       # End cluster, do 1 or more times
 \}\}                     # Closing brace '}}'

Upvotes: 1

ChadF
ChadF

Reputation: 1758

Simple and not full regex solution (in the event we can't come up with one). Use your regex, and then filter the array that it returns.

Functional Code:

var reg = /{{\s*.*?\s*}}/g;

var testStr = "test {{debug}} {{contact.language}} test {{another}}";

var result = testStr.match(reg).filter(function(str){
    if(str === "{{contact.firstName}}" |
       str === "{{contact.lastName}}" |
       str === "{{contact.phoneNumber}}" |
       str === "{{contact.language}}") {
        return false   
    } else {
        return true;
    }
});

console.log(result);
// [ "{{debug}}", "{{another}}"]

Upvotes: 0

Related Questions