0

I am putting together a syntax highlighter for the Expression Engine templating language. I am trying to grab double quotes and their value only inside of an {if} tag.

Example

{if layout:test == "test" || another == "value"}
 {if:elseif param == "value"}
 {if:else}
{/if}

Regular Expression

{if.+?(?=")(")([^"]*)(")

The problem is that it only ever captures the first one and not the next one. How can I make it select all of them within a conditional block only?

Desired Matches

"test", "value"
ctwheels
  • 21,901
  • 9
  • 42
  • 77
Miura-shi
  • 4,409
  • 5
  • 36
  • 55

1 Answers1

2

Brief

I would suggest breaking your logic into two parts (2 separate regular expressions). The first regex should match the if block and the second should match the variables within it. The reason you are unable to grab the second variable in the first {if} block is due to the way regular expressions work. They will only capture 1 group if you're matching a string (unless you explicitly tell it to potentially match 2 groups, in which case you won't capture the third group unless you do the same, etc.).


Code

Capture blocks

See this code in use here

{(?:(?<if>if(?=\s+))|(?<elseif>if:elseif(?=\s+)))\s*((?:[^"]*?|"[^"]*")*)\s*}

Gather variable values

See this code in use here

[\w:]+\s*==\s*"([^"]*)"

Results

Input - Capture blocks

{if layout:test == "test" || another == "}"}
 {if:elseif param == "value"}
 {if:else}
{/if}

Output - Capture blocks

  • Group if
    • Group 3: layout:test == "test" || another == "}"
  • Group elseif
    • Group 3: param == "value"

Input - Gather variable values

layout:test == "test" || another == "}"
param == "value"

Output - Gather variable values

test
}
value

Explanation

Capture blocks

  • { Match this character literally
  • (?:(?<if>if(?=\s+))|(?<elseif>if:elseif(?=\s+))) Capture either if into group named if, which is followed by at least one whitespace character, or capture if:elseif into group named elseif, which is followed by at least one whitepsace character
  • \s* Match any number of whitespace characters
  • ((?:[^"]*?|"[^"]*")*) Capture any number of either of the following
    • [^"]*? Match any character except " any number of times, but as few as possible
    • "[^"]*" Match a ", followed by any character except " any number of times, followed by "
  • \s* Match any number of whitespace characters

Gather varaible values

  • [\w:]+ Match any word character \w or colon : between one and unlimited times
  • \s* Match any whitespace character any number of times
  • == Match == literally
  • \s* Match any whitespace character any number of times
  • " Match " literally
  • ([^"]*) Capture any character except " any number of times
  • " Match " literally
ctwheels
  • 21,901
  • 9
  • 42
  • 77