Question

I want to replace all line breaks but only if they're not preceded by these two characters {] (both, not one of them) using JavaScript. The following expression seems to do the job but it breaks other regex results so something must be wrong:

/[^\{\]]\n/g

What am I doing wrong?

Was it helpful?

Solution

Do you need to be able to strip out \n, \r\n, or both?

This should do the job:

/(^|^.|[^{].|.[^\]])\r?\n/gm

And would require that you place $1 at the beginning of your replacement string.

To answer your question about why /[^\{\]]\n/ is wrong, this regex equates to: "match any character that is neither { nor ]", followed by \n, so this incorrectly fail to match the following:

here's a square]\n
see the following{\n

You're also missing the g flag at the end, but you may have noticed that.

OTHER TIPS

When you're using [^\{\]] you're using a character range: this stands for "any character which is not \{ or \]. Meaning the match will fail on {\n or }\n.

If you want to negate a pattern longer than one character you need a negative look-ahead:

/^(?!.*{]\n)([^\n]*)\n/mg

^(?!          # from the beginning of the line (thanks to the m flag)
    .*{]\n    # negative lookahead condition: the line doesn't end with {]\n
)
([^\n]*)      # select, in capturing group 1, everything up to the line break
\n

And replace it with

$1 + replacement_for_\n

What we do is check line by line that our line doesn't hold the unwanted pattern.

If it doesn't, we select everything up to the ending \n in capturing group 1, and we replace the whole line with that everything, followed by what you want to replace \n with.

Demo: http://regex101.com/r/nM2xE1

Look behind is not supported, you could emulate it this way

stringWhereToReplaceNewlines.replace(/(.{0,2})\n/g, function(_, behind) {
  return (behind || "") + ((behind === '{]') ? "\n" : "NEWLINE_REPLACE")
})

The callback is called for every "\n" with the 2 preceding characters as the second parameter. The callback must return the string replacing the "\n" and the 2 characters before. If the 2 preceding characters are "{]" then the new line should not be replaced so we return exactly the same string matched, otherwise we return the 2 preceding characters (possibly empty) and the thing that should replace the newline

My solution would be this:

([^{].|.[^\]])\n

Your replacement string should be $1<replacement>

Since JavaScript doesn't support lookbehind, we have to make do with lookahead. This is how the regex works:

  • Anything but { and then anything - [^{].
  • Or anything and then anything but ] - .[^\]]
  • Put simply, [^{].|.[^\]] matches everything that .. matches except for {]
  • Finally a \n

The two chars before the \n are captured, so you can reinsert them into the replacement string using $1.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top