0

I'm trying to write out a regex that checks that the following has been written:

session({
  secret: "asdfadf",
  resave: false,
  saveUninitialized: false,
});

The regex test I wrote can be found here:

session\(\{\s*secret\:\s*("|')\w*("|')\s*,\s*resave\s*\:\s*false\,\s*saveUninitialized\:\s*false\,?\s*\}\)

I need to update it so that the properties can be added in different orders and still pass the regex test. Is there a group or a way to set this so it passes?

user7496931
  • 1,347
  • 3
  • 15
  • 32
  • 2
    ```I need to update it```, what do you mean to update it? What exactly do you want to achieve? – ikhvjs Jun 08 '21 at 15:40
  • The current regex checks for the properties in that session object to exist, but it fails if someone adds them in a different order. I.e. if someone adds `resave` before `secret` the regex test fails. – user7496931 Jun 08 '21 at 15:43
  • 2
    Why do you need to check this? The options object pass to the session should be irrelevant. – ikhvjs Jun 08 '21 at 15:46
  • It's a specific use-case. I need to make sure that if someone adds these three objects in different order, the regex will still pass. – user7496931 Jun 08 '21 at 15:47
  • Do you want to make sure the object pass to session function contains only 3 keys: secret, resave, saveUninitialized ? – ikhvjs Jun 08 '21 at 15:49
  • 1
    Yes, just those three in any order. – user7496931 Jun 08 '21 at 15:57
  • With all the efficient ways JavaScript has to check object keys and properties, why Regex? – ISAE Jun 08 '21 at 15:57
  • This is a very specific use case that I don't want to elaborate on tbh. I understand the question is odd and doesn't make sense, but it's what I'm seeking to accomplish. – user7496931 Jun 08 '21 at 16:04
  • 1
    This is horrible and I urge you to reconsider. Otherwise, you might consider the brute force approach of creating 6 alternations `(match1)|(match2)` etc.. to cover the possible permutations of 3 items. – spender Jun 08 '21 at 16:13
  • the 6 alternations would be matching the 3 different orders? Is there a way to write a regex that checks if the groups are included in the object (while ignoring the order)? – user7496931 Jun 08 '21 at 16:15
  • Yes, see here: https://stackoverflow.com/a/3102205/14357 but there's no easy way to deal with the optional trailing comma. [This](https://regex101.com/r/QSiexA/1) is the best I could come up with using this approach. – spender Jun 08 '21 at 16:28
  • I know you may not want to explain your reason to use Regex. I just check your previous question, is it because you may have a chance to add more properties in your object? – ikhvjs Jun 08 '21 at 18:15
  • I've shortened the regex significantly and added further explanation. – MikeM Jun 09 '21 at 18:26

1 Answers1

2

If we want to create a regular expression that matches a string comprised of the substrings

Doe Ray Me Far Sew La Tea

in any order, and we don't want to tediously create a very long expression including every possible ordering, we may begin by trying

(Doe|Ray|Me|Far|Sew|La|Tea){7}

which matches a string containing the seven substrings in any order.

We then have the problem that the expression does not fail to match if one or more substrings is repeated or missing.

One way to ensure each substring appears only once is to add a negative lookahead to each alternative to ensure it doesn't appear in the string again ahead of the match.

(Doe(?!.*D)|Ray(?!.*R)|Me(?!.*M)|Far(?!.*F)|Sew(?!.*S)|La(?!.*L)|Tea(?!.*T)){7}

Note that only the first letter of the substring is required in the lookahead because the first letter of each substring is different.

In your particular case, the following seems to work fine although it hasn't been thoroughly tested.

The final trailing comma is made optional by (,|(?=\s*\})), which ensures that if there isn't a comma then there must be a '}' ahead in the string after optional whitespace.

You may not want to make the semicolon optional as done here.

You may also want to split a long regular expression into multiple lines.

const input = `session({
  secret: "asdfadf",
  resave: false,
  saveUninitialized: false,
});`;

const regex = /^session\s*\(\s*\{\s*((secret\s*:\s*(?<q>["'])\w*\k<q>(?!.*c)|resave\s*\:\s*false(?!.*e\s*:)|saveUninitialized\s*:\s*false(?!.*d\s*:))\s*(,|(?=\s*\}))\s*){3}\}\s*\)\s*;?$/;

console.log(regex.test(input));
MikeM
  • 13,156
  • 2
  • 34
  • 47