Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it impossible to indicate the start of the input string using a multiline regex pattern in JavaScript?

In JavaScript, the multiline flag changes the meaning of ^ and $:

Treat beginning and end characters (^ and $) as working over multiple lines (i.e., match the beginning or end of each line (delimited by \n or \r), not only the very beginning or end of the whole input string)

Well, with those characters out of the picture, are there any other ways to mark the start of the input string? How can I indicate that I want my multiline pattern to only match at the start of the input string?

I know I can check the index of the match using the index property of the return value of exec, but is there a way to prevent the regex engine from searching the entire string in the first place?

like image 635
aeskr Avatar asked Sep 17 '25 09:09

aeskr


2 Answers

No, ^ is the only built-in assertion that tests for beginning-of-input and, as you said, its behavior is modified by the multiline flag.

You could put some unique string at the beginning of the string you're testing and also at the beginning of your regular expression, but that's a bit of a hack. In the normal case, as you said, you'd test the index of the returned match.

like image 116
T.J. Crowder Avatar answered Sep 18 '25 22:09

T.J. Crowder


In 2021, with the growing adoption of the ECMAScript 2018+ standard that supports the lookbehind construct in a RegExp, you can now use an "absolute", unambiguous start of string position in the multiline mode regex if you use

/^(?<![^])/gm

Although the g flag allows multiple matching and m allows ^ to match any line start position, the ^(?<![^]) pattern only matches

  • ^ - start of a line that
  • (?<![^]) - has no char immediately to the left of it. [^] matches any char in an ECMAScript regex.

Alternatives:

/^(?<![\w\W])/gm
/^(?<!.)/gsm

where [\w\W] matches any chars including line breaks (a synonymic contruct to [\s\S] and [\d\D]), and /s flag makes . line break aware.

See the JavaScript demo:

const regex = /^(?<![^])/gm; // g - multiple matching enabled!
const text = 'Line 1\nLine 2\nLine 3';
console.log(text.replace(regex, 'INSERTION...')); // Only the first line affected
// => INSERTION...Line 1
//    Line 2
//    Line 3
like image 30
Wiktor Stribiżew Avatar answered Sep 18 '25 23:09

Wiktor Stribiżew