4

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?

Kyuzu
  • 93
  • 6

6 Answers6

9

Also this will match .scss, .sass and .css only, it is very readable and self-explanatory

/\.(sc|sa|c)ss$/
Fabrizio Calderan
  • 120,726
  • 26
  • 164
  • 177
  • Maybe even more readible would be `\.(?:s?c|sa)ss`? – JvdV Mar 02 '22 at 08:33
  • This is the simplest one yet. I prefer `/\.(sc|sa|c)ss$/` over `/\.(?:s?c|sa)ss/` since the first is very simple. Thanks! – Kyuzu Mar 02 '22 at 08:41
3

Another way using alternation:

\.((?:s[ac]|c)ss)$

RegEx Demo

Here this non-capturing group (?:s[ac]|c) will match sa or sc or just c.

anubhava
  • 761,203
  • 64
  • 569
  • 643
3

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 :)

Demo

Martijn
  • 15,791
  • 4
  • 36
  • 68
2

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.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
1

You could just list the ones you want to match:

let rx = /\.css|\.sass|\.scss/; // alphabetized for future maintenance 

This isn't fancy, but it is very clear and easy to add more later.

I tested it here : enter image description here

Lonnie Best
  • 9,936
  • 10
  • 57
  • 97
0

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 1
  • ss$ Match ss at the end of the string

Regex demo

\.(s[ac]|c)ss$

A variation on the previous pattern, now matching sa or sc or c

Regex demo

If in your environment the lookbehind assertion is supported:

\.s?[ac]ss$(?<!\.ass)
  • \.s? Match a . and optional s
  • [ac] Match either a or c
  • ss$ Match ss at the end of the string
  • (?<!\.ass) Negative lookbehind, assert not .ass to the left

Regex demo

Note that if you want a match only, you can also use a non capture group (?:...) instead.

The fourth bird
  • 154,723
  • 16
  • 55
  • 70