Matching key/value pairs with comments

Viewed 153

For a JavaScript application, I'm trying to come up with a regex that will match key/value pairs in a string. It's working pretty well, but there is one last thing that I need to implement and I'm not sure how.

The syntax is very similar to what you'll find in a .env file. So key/value pairs look like KEY=value.

A few rules that I have already implemented:

  • The key
    • alphanumeric string.
    • can't be empty and can't be a number.
    • may contain an underscore
  • The value
    • can be string
    • may be surrounded by single or double quotes, or none at all.

Now I'm trying to add comments with # in there. It works, except when # is between the quotes. Any idea how to fix that? Thanks!

Here is my code sample:

// This is my regex
const regex = /^\s*(?![0-9_]*\s*=\s*([\W\w\s.]*)\s*$)[A-Z0-9_]+\s*=\s*(.*)?\s*(?<!#.*)/gi;


// Outputs [ "KEY=value " ] --> OK
const str = `KEY=value # Comment`;
console.log(str.match(regex));

// Outputs [ "KEY2=val" ] --> OK
const str2 = `KEY2=val#ue # Comment`;
console.log(str2.match(regex));

// Outputs [ "key3='value3' " ] --> OK
const str3 = `key3='value3' # Comment`;
console.log(str3.match(regex));

// Outputs [ "key_4='val" ] --> NOT OK
// Expecting [ "key_4='val#ue4' " ]
const str4 = `key_4='val#ue4' # Comment`;
console.log(str4.match(regex));

EDIT:

Here is another sample for testing:

# The following are matching
ONE = This is ONE
TWO=This is TWO
 THREE="This is 'THREE'"
 FOUR = "This is \"FOUR\""
fi_ve = 'This is \'FIVE\''
 six='This is "SIX"'
NUMBER7="This is SEVEN" # Comment for SEVEN
number8="This is EIGHT"#Comment for EIGHT
NINE="This is #9"
TEN=This is #10
ELEVEN=
TWELVE=10
THIRTEEN=TRUE
FOURTEEN="true"
FIFTEEN=false
SIXTEEN='FALSE'

# The following are not matching(incl. empty line)
17="Is not valid because the key is a number"

="Is also not valid because the key is missing"
1 Answers

You may use

([A-Za-z_]\w*)[ \t]*=[ \t]*('[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"|[^\r\n#]*)

See the regex demo

  • ([A-Za-z_]\w*) - Group 1:
  • [ \t]*=[ \t]* - a = enclosed with 0 or more spaces or tabs
  • ('[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"|[^\r\n#]*) - Group 2:
    • '[^'\\]*(?:\\.[^'\\]*)*'| - a '...' like substring that may contain any string escape sequence, or
    • "[^"\\]*(?:\\.[^"\\]*)*"| - a "..." like substring that may contain any string escape sequence, or
    • [^\r\n#]* - 0 or more chars other than #, CR and LF
Related