1
// 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.

Joseph
  • 117,725
  • 30
  • 181
  • 234
  • 1
    When the `c` in `{{contact.language}}` is consumed by `.*?`, the remaining `ontact.language}}` is not matched by any of `contact\.firstName|contact\.lastName|contact\.phoneNumber|contact\.language`. – Gumbo Jun 28 '15 at 19:43
  • In short, you want to discard all that begins with `contact.`? – Casimir et Hippolyte Jun 28 '15 at 20:15
  • @CasimiretHippolyte It just so happens that the text I want to search all has `contact.` but it could be anything, not just `contact.`. – Joseph Jun 28 '15 at 20:48

3 Answers3

1

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 '}}'
  • It so happens that all the text I didn't want to match has `contact.`, but it could be any text actually. – Joseph Jun 28 '15 at 20:50
  • @JosephtheDreamer - It really doesn't matter what you don't want to match does it ? I mean, what the above describes is a template to put your `stuff` into .. `\{\{(?!(?#stuff)\}\})(?:(?!\{\{|\}\})[\S\s])+\}\}` –  Jun 28 '15 at 20:58
0

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}}"]
ChadF
  • 1,750
  • 10
  • 22
0

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

Community
  • 1
  • 1
Jan
  • 5,688
  • 3
  • 27
  • 44