2

For a number of reasons (one of them my lameness) I get extremely confused when it comes to whitespace and newlines in regexps.

Say for example that I want to search for an equal sign (=) followed by any number of whitespace and newline characters.

At certain points in time I have done the following in the belief that these regexps are equivalent:

"=[\s\n]*"
"=[\s-\n]*"
"=[\s]*"
"=[\s-]*"
"=\s*"
"=\s-*"

They are not.

The Emacs regexp docs just manage to confuse me on this one. :-(

  • 1
    What is the usage situation? Are the given examples regular expression strings in a elisp program or are they input to some search command. If they are strings in a elisp program then \s expands to a space and \n expands to a newline. You need to escape the backslash if you want to use it as character in the regexp. Considering that the regexp with the space syntax class matcher in it looks like "=\\s-*". Note that \\s- does not work in character classes like [\\s-\n]. Use [[:space:]\n] instead. – Tobias Nov 18 '18 at 14:23
  • Elisp only, i.e. in other words: In character classes I can with minimal confusion use "=[[:blank:]\n]*") to do what I ask for. To match a sequence of whitespace chars outside of a character class use "\s*" for minimal confusion. "\s" and "[:blank:]" never matches a \n. – Joakim G. Nov 18 '18 at 17:09
  • 2
    Beware that "\s*" is the string " *". It matches spaces (char-code 32) and only spaces. If you want to match all characters belonging to the whitespace syntax class you should use "\\s-*" instead. Note the double-backslash which represents one backslash character in the string/regexp. – Tobias Nov 18 '18 at 19:21
  • Now I see. I'm dense as lead. Constructs like "=[[:blank:]\n]*" and "foo\\s-*bar"is what I actually mean most of the time. Thanks! – Joakim G. Nov 19 '18 at 11:00
3

You could always use one of the character classes. I would say use [:blank:] when the usage context is textual, and use [:space:] when it is programmatic, i.e. plain text vs source code.

When entered interactively, this seems to work: =[[:blank:]^J]*. You can enter ^J by just quoting your newline: C-q C-j. In elisp the usual \n works.

I tested interactive use with highlight-regexp and isearch-forward-regexp, and elisp use with M-: (search-forward-regexp "=[[:blank:]\n]*").

Edit: (to clarify comments)

If you compare the docs for \s with that for [[:blank:]]* (linked above), the latter is a superset. If your use case considers characters like tab as whitespace, you should use the latter, if not, \s should be fine.

A couple of examples:

  1. Say you are looking for a name (variable, function, etc) in C++ source, \s would be sufficient.
  2. You want to change the indentation in a plain text notes file, [:blank:] would be better suited.

Although, this may not be a hard and fast rule, as many source files can contain tabs as whitespace. That's exactly why this is for you to judge case by case.

  • Yes. Using [:blank:] will put an end to my confusion. I will stay away from the \s- whitespace character class and ignore all who says that newline is a whitespace char included in \s or [:blank:]. /Thanks! – Joakim G. Nov 18 '18 at 14:50
  • The question still valid is if I should use "\s*" or "[[:blank:]]*" to eat whitespaces only. – Joakim G. Nov 18 '18 at 14:58
  • I tried to add some clarifications in an edit, maybe that addresses your questions? – suvayu Nov 19 '18 at 11:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.