Block a comma using regular expressions in multiline text

Viewed 273

I have a specific validation scenario that I am trying to solve using regexp pattern in JavaScript. I am struggling to write a suitable regular expression.

The rule is that validation must fail if a comma appears anywhere within a multiline piece of text that is enterred by the user into a text area, but only if it appears BEFORE a pipe character on the same line. It is assumed that every line will contain a pipe character somewhere (this is enforced elsewhere).

Examples below should clarify the requirement:

Example 1 - PASS: No commas

one|One
two|Two
three|Three

Example 2 - PASS: Comma appears, but after pipe character and so is ok

one|One
two|Tw,o
three|Three

Example 3 - FAIL: Comma appears before pipe character

o,ne|One
two|Two
three|Three

Example 4 - FAIL: Comma appears before pipe character

one|One
two,|Two
three|Three

The closest attempt I have got so far is:

/^[^,]+$/g

However, this doesn't take into account that a comma after the pipe character is permitted.

2 Answers

One approach could be using a negative lookahead to assert that the line does not contain a pipe after a comma.

^(?![^,\r\n]*,[^\r\n|]*\|).*(?:\r?\n(?![^,\r\n]*,[^\r\n|]*\|).*)*$

In parts

  • ^ Start of the string
  • (?![^,\r\n]*,[^\r\n|]*\|) Assert not a comma before a pipe char
  • .* Match the whole line
  • (?: Non capture group
    • \r?\n match a newline
    • (?![^,\r\n]*,[^\r\n|]*\|) Assert not a comma before a pipe char
    • .* Match the whole line
  • )* Close the group and repeat 0+ times to optionally match all the following lines
  • $ End of string.

Regex demo no match | Regex demo match

As per my comment: If you could negate the logic and react to not matching a bad pattern (!badPattern.test(str)), the whole thing becomes a lot easier.

For example:

const cases = [
// good
`one|One
two|Two
three|Three`,

// good
`one|One
two|T,wo
three|Three`,

// bad
`one|One
two,|Two
three|Three`,
];

const badPattern = /,.*\|/;

const out = cases.map(val => ({
    input: val,
    result: !badPattern.test(val) ? 'good' : 'bad',
}))

console.log(out);

Related