I have the following regex: /\.([s]?[ac]ss)$/. The problem is, it matches .scss, .sass, .css, .ass. How would I make it not match .ass?
You can use
\.(?!a)(s?[ac]ss)$
See the regex demo. Details:
\. - a dot(?!a) - the next char cannot be a(s?[ac]ss) - Group 1: an optional s, a or c and then ss$ - end of string.Another regex that can work is
\.(s(?:css|ass)|css)$
See this regex demo. Details:
\. - a dot(s(?:css|ass)|css) - s and then css or ass or css$ - end of string.NOTE: if you have a dynamic, user-defined list of such fixed strings to match after a . at the end of string, you can build these regexes automatically using the code at the bottom of my answer.
Also this will match .scss, .sass and .css only, it is very readable and self-explanatory
/\.(sc|sa|c)ss$/
Another way using alternation:
\.((?:s[ac]|c)ss)$
Here this non-capturing group (?:s[ac]|c) will match sa or sc or just c.
How about just
/\.(s?css|sass)$/
Regex doesn't need to be very complex to work. This is a lot easier to read for other programmers (i.e. you in about 3 months) and does the same.
Sure you can smush it more together, but why would you? Regex are complicated enough, keep 'm simple if you can :)
In your pattern \.([s]?[ac]ss)$ you match .ass because the leading s optional and the character class [ac] can match both characters.
Instead you could use lookarounds assertions, or use an alternation | to allow only certain alternatives.
Some other variations could be:
\.(s?c|sa)ss$
\.Match a .( Capture group 1
s?c|sa Match an optional s then match c or match sa) Close group 1ss$ Match ss at the end of the string\.(s[ac]|c)ss$
A variation on the previous pattern, now matching sa or sc or c
If in your environment the lookbehind assertion is supported:
\.s?[ac]ss$(?<!\.ass)
\.s? Match a . and optional s[ac] Match either a or css$ Match ss at the end of the string(?<!\.ass) Negative lookbehind, assert not .ass to the leftNote that if you want a match only, you can also use a non capture group (?:...) instead.