584

For example, this regex

(.*)<FooBar>

will match:

abcde<FooBar>

But how do I get it to match across multiple lines?

abcde
fghij<FooBar>
Bobulous
  • 12,967
  • 4
  • 37
  • 68
andyuk
  • 38,118
  • 16
  • 52
  • 52
  • 1
    To clarify; I was originally using Eclipse to do a find and replace in multiple files. What I have discovered by the answers below is that my problem was the tool and not regex pattern. – andyuk Oct 02 '08 at 15:45

26 Answers26

664

Try this:

((.|\n)*)<FooBar>

It basically says "any character or a newline" repeated zero or more times.

levik
  • 114,835
  • 27
  • 73
  • 90
  • 7
    This is dependent on the language and/or tool you are using. Please let us know what you are using, eg Perl, PHP, CF, C#, sed, awk, etc. – Ben Doom Oct 01 '08 at 18:57
  • 67
    Depending on your line endings you might need `((.|\n|\r)*)` – Potherca Mar 09 '12 at 17:27
  • 3
    He said he is using Eclipse. This is correct solution in my opinion. I have same problem and this solved it. – Danubian Sailor Apr 18 '12 at 08:14
  • 4
    Right - the question is about eclipse and so are the tags. But the accepted solution is a PHP solution. Yours should be the accepted solution... – acme Jun 13 '12 at 12:04
  • 2
    `\R` matches line endings in a platform-independent manner. In eclipse, at least, and some other tools. – frIT Oct 05 '15 at 20:20
  • 1
    Very funny, I tried this on gedit and I got a segmentation fault. Murphy's law at its finest. – Manolis Agkopian Oct 13 '15 at 01:06
  • 53
    This is the worst regex for matching multiple line input. Please never use it unless you are using ElasticSearch. Use `[\s\S]*` or `(?s).*`. – Wiktor Stribiżew Jul 18 '16 at 11:05
  • 4
    Such needless alternation can result in catastrophic backtracking in some situations. This isn't a good general pattern. – Snow Apr 25 '19 at 02:24
  • I like this. This is more general. – lkahtz Sep 04 '20 at 04:59
  • In `xml` files, I use : `((.|\n|\r|\t)*)` pattern – Nolwennig Apr 20 '21 at 15:29
  • @Wiktor Stribiżew: *Why* is it the worst? Will the other match newlines without modifiers? – Peter Mortensen Nov 18 '21 at 23:08
  • 4
    @PeterMortensen Too many people have already reported peformance issues and even stack overflow errors when using this pattern, and I have even recorded a [YT video](https://www.youtube.com/watch?v=SEobSs-ZCSE) with explanation of why it is that bad. – Wiktor Stribiżew Nov 18 '21 at 23:34
  • This should be marked as best answer. – Thomas Easo Jul 20 '22 at 17:15
  • @ThomasEaso this should be removed from SO as it is one of the worst regex answers here. – Wiktor Stribiżew Mar 03 '23 at 10:20
  • @WiktorStribiżew Seems like the way you suggested it works even faster? Because when I run the original query in Intellij IDEA it freezed for some time :D – Frankie Drake May 04 '23 at 08:16
  • 1
    @FrankieDrake `(.|\n)*` will freeze with longer texts, so it is not even a question of speed, but safety. [My answer](https://stackoverflow.com/a/45981809/3832970) provides the right way to match newline-containing texts in most languages/environments. – Wiktor Stribiżew May 04 '23 at 08:57
305

It depends on the language, but there should be a modifier that you can add to the regex pattern. In PHP it is:

/(.*)<FooBar>/s

The s at the end causes the dot to match all characters including newlines.

Paige Ruten
  • 172,675
  • 36
  • 177
  • 197
208

The question is, can the . pattern match any character? The answer varies from engine to engine. The main difference is whether the pattern is used by a POSIX or non-POSIX regex library.

A special note about : they are not considered regular expressions, but . matches any character there, the same as POSIX-based engines.

Another note on and : the . matches any character by default (demo): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match'); (tokens contain a abcde\n fghij item).

Also, in all of 's regex grammars the dot matches line breaks by default. Boost's ECMAScript grammar allows you to turn this off with regex_constants::no_mod_m (source).

As for (it is POSIX based), use the n option (demo): select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual

POSIX-based engines:

A mere . already matches line breaks, so there isn't a need to use any modifiers, see (demo).

The (demo), (demo), (TRE, base R default engine with no perl=TRUE, for base R with perl=TRUE or for stringr/stringi patterns, use the (?s) inline modifier) (demo) also treat . the same way.

However, most POSIX-based tools process input line by line. Hence, . does not match the line breaks just because they are not in scope. Here are some examples how to override this:

  • - There are multiple workarounds. The most precise, but not very safe, is sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/' (H;1h;$!d;x; slurps the file into memory). If whole lines must be included, sed '/start_pattern/,/end_pattern/d' file (removing from start will end with matched lines included) or sed '/start_pattern/,/end_pattern/{{//!d;};}' file (with matching lines excluded) can be considered.
  • - perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str" (-0 slurps the whole file into memory, -p prints the file after applying the script given by -e). Note that using -000pe will slurp the file and activate 'paragraph mode' where Perl uses consecutive newlines (\n\n) as the record separator.
  • - grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file. Here, z enables file slurping, (?s) enables the DOTALL mode for the . pattern, (?i) enables case insensitive mode, \K omits the text matched so far, *? is a lazy quantifier, (?=<Foobar>) matches the location before <Foobar>.
  • - pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file (M enables file slurping here). Note pcregrep is a good solution for macOS grep users.

See demos.

Non-POSIX-based engines:

  • - Use the s modifier PCRE_DOTALL modifier: preg_match('~(.*)<Foobar>~s', $s, $m) (demo)
  • - Use RegexOptions.Singleline flag (demo):
    - var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
    - var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
  • - Use the (?s) inline option: $s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
  • - Use the s modifier (or (?s) inline version at the start) (demo): /(.*)<FooBar>/s
  • - Use the re.DOTALL (or re.S) flags or (?s) inline modifier (demo): m = re.search(r"(.*)<FooBar>", s, flags=re.S) (and then if m:, print(m.group(1)))
  • - Use Pattern.DOTALL modifier (or inline (?s) flag) (demo): Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
  • - Use RegexOption.DOT_MATCHES_ALL : "(.*)<FooBar>".toRegex(RegexOption.DOT_MATCHES_ALL)
  • - Use (?s) in-pattern modifier (demo): regex = /(?s)(.*)<FooBar>/
  • - Use (?s) modifier (demo): "(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
  • - Use the s (dotAll) flag or workarounds [^] / [\d\D] / [\w\W] / [\s\S] (demo): s.match(/([\s\S]*)<FooBar>/)[1]
  • (std::regex) Use [\s\S] or the JavaScript workarounds (demo): regex rex(R"(([\s\S]*)<FooBar>)");
  • - Use the same approach as in JavaScript, ([\s\S]*)<Foobar>. (NOTE: The MultiLine property of the RegExp object is sometimes erroneously thought to be the option to allow . match across line breaks, while, in fact, it only changes the ^ and $ behavior to match start/end of lines rather than strings, the same as in JavaScript regex)
  • - Use the /m MULTILINE modifier (demo): s[/(.*)<Foobar>/m, 1]
  • - Base R PCRE regexps - use (?s): regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2] (demo)
  • - in stringr/stringi regex funtions that are powered with the ICU regex engine. Also use (?s): stringr::str_match(x, "(?s)(.*)<FooBar>")[,2] (demo)
  • - Use the inline modifier (?s) at the start (demo): re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
  • - Use dotMatchesLineSeparators or (easier) pass the (?s) inline modifier to the pattern: let rx = "(?s)(.*)<Foobar>"
  • - The same as Swift. (?s) works the easiest, but here is how the option can be used: NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
  • , - Use the (?s) modifier (demo): "(?s)(.*)<Foobar>" (in Google Spreadsheets, =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>"))

NOTES ON (?s):

In most non-POSIX engines, the (?s) inline modifier (or embedded flag option) can be used to enforce . to match line breaks.

If placed at the start of the pattern, (?s) changes the bahavior of all . in the pattern. If the (?s) is placed somewhere after the beginning, only those .s will be affected that are located to the right of it unless this is a pattern passed to Python's re. In Python re, regardless of the (?s) location, the whole pattern . is affected. The (?s) effect is stopped using (?-s). A modified group can be used to only affect a specified range of a regex pattern (e.g., Delim1(?s:.*?)\nDelim2.* will make the first .*? match across newlines and the second .* will only match the rest of the line).

POSIX note:

In non-POSIX regex engines, to match any character, [\s\S] / [\d\D] / [\w\W] constructs can be used.

In POSIX, [\s\S] is not matching any character (as in JavaScript or any non-POSIX engine), because regex escape sequences are not supported inside bracket expressions. [\s\S] is parsed as bracket expressions that match a single character, \ or s or S.

InSync
  • 4,851
  • 4
  • 8
  • 30
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 14
    You should link to this excellent overview from your profile page or something (+1). – Jan Oct 15 '17 at 20:15
  • 1
    You may want to add this to the _boost_ item: In the regex_constants namespace, flag_type_'s : perl = ECMAScript = JavaScript = JScript = ::boost::regbase::normal = 0 which defaults to Perl. Programmers will set a base flag definition `#define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_m` for thier regex flags to reflect that. And the arbitor is _always_ the inline modifiers. Where `(?-sm)(?s).*` resets. –  Apr 26 '18 at 21:30
  • 1
    Can you also add for bash please? – Pasupathi Rajamanickam Dec 19 '18 at 02:12
  • 3
    @PasupathiRajamanickam Bash uses a POSIX regex engine, the `.` matches any char there (including line breaks). See [this online Bash demo](https://ideone.com/d1XTpR). – Wiktor Stribiżew Dec 19 '18 at 07:33
  • Thanks for the ?s modifier for PowerShell; cleaned up my fragile regex to something a bit sturdier. – Adam Wenger Mar 02 '20 at 19:46
  • 1
  • 3
    You rock — this is the most exhaustive mini-tutorial on (relatively) complex regexp's that I've ever seen. You deserve that your answer becomes the accepted one! Kudos and extra votes for including `Go` in the answer! – Gwyneth Llewelyn May 13 '20 at 00:29
  • Golden, indeed! – fl00r Dec 26 '22 at 14:17
73

If you're using Eclipse search, you can enable the "DOTALL" option to make '.' match any character including line delimiters: just add "(?s)" at the beginning of your search string. Example:

(?s).*<FooBar>
Paulo Merson
  • 13,270
  • 8
  • 79
  • 72
46
([\s\S]*)<FooBar>

The dot matches all except newlines (\r\n). So use \s\S, which will match ALL characters.

vvvvv
  • 25,404
  • 19
  • 49
  • 81
samwize
  • 25,675
  • 15
  • 141
  • 186
43

In many regex dialects, /[\S\s]*<Foobar>/ will do just what you want. Source

fearless_fool
  • 33,645
  • 23
  • 135
  • 217
Abbas Shahzadeh
  • 431
  • 4
  • 2
  • 4
    From that link: "JavaScript and VBScript do not have an option to make the dot match line break characters. In those languages, you can use a character class such as [\s\S] to match any character." Instead of the . use [\s\S] (match spaces and non-spaces) instead. – Allen May 09 '13 at 15:34
23

We can also use

(.*?\n)*?

to match everything including newline without being greedy.

This will make the new line optional

(.*?|\n)*?
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nambi_0915
  • 1,091
  • 8
  • 21
18

In Ruby you can use the 'm' option (multiline):

/YOUR_REGEXP/m

See the Regexp documentation on ruby-doc.org for more information.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
9

"." normally doesn't match line-breaks. Most regex engines allows you to add the S-flag (also called DOTALL and SINGLELINE) to make "." also match newlines. If that fails, you could do something like [\S\s].

Markus Jarderot
  • 86,735
  • 21
  • 136
  • 138
8

For Eclipse, the following expression worked:

Foo

jadajada Bar"

Regular expression:

Foo[\S\s]{1,10}.*Bar*
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Gordon
  • 81
  • 1
  • 1
6

Note that (.|\n)* can be less efficient than (for example) [\s\S]* (if your language's regexes support such escapes) and than finding how to specify the modifier that makes . also match newlines. Or you can go with POSIXy alternatives like [[:space:][:^space:]]*.

tye
  • 1,157
  • 9
  • 11
6

In notepad++ you can use this

<table (.|\r\n)*</table>

It will match the entire table starting from

rows and columns

You can make it greedy, using the following, that way it will match the first, second and so forth tables and not all at once

<table (.|\r\n)*?</table>
TheTechGuy
  • 16,560
  • 16
  • 115
  • 136
6

This works for me and is the simplest one:

(\X*)<FooBar>
Mateusz Kaflowski
  • 2,221
  • 1
  • 29
  • 35
  • thanks...this helped me to create multiline regex for me i.e Pattern regex = Pattern.compile("(\\X*)From:*(\\X*)Sent:*(\\X*)To:*"); – Narendra Pandey Jun 08 '23 at 12:41
5

Use:

/(.*)<FooBar>/s

The s causes dot (.) to match carriage returns.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bill
  • 4,323
  • 8
  • 28
  • 32
  • Seems like this is invalid (Chrome): text.match(/a/s) SyntaxError: Invalid flags supplied to RegExp constructor 's' – Allen May 09 '13 at 15:31
  • Because it is unsupported in JavaScript RegEx engines. The `s` flags exists in PCRE, the most complete engine (available in Perl and PHP). PCRE has 10 flags (and a lot of other features) while JavaScript has only 3 flags (`gmi`). – Morgan Touverey Quilling Apr 20 '16 at 18:51
5

Use RegexOptions.Singleline. It changes the meaning of . to include newlines.

Regex.Replace(content, searchText, replaceText, RegexOptions.Singleline);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
shmall
  • 51
  • 1
  • 1
4

In a Java-based regular expression, you can use [\s\S].

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kamahire
  • 2,149
  • 3
  • 21
  • 50
3

Generally, . doesn't match newlines, so try ((.|\n)*)<foobar>.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
tloach
  • 8,009
  • 1
  • 33
  • 44
  • 5
    No, don't do that. If you need to match anything including line separators, use the DOTALL (a.k.a. /s or SingleLine) modifier. Not only does the (.|\n) hack make the regex less efficient, it's not even correct. At the very least, it should match \r (carriage return) as well as \n (linefeed). There are other line separator characters, too, albeit rarely used. But if you use the DOTALL flag, you don't have to worry about them. – Alan Moore Apr 26 '09 at 03:17
  • 2
    \R is the platform-independent match for newlines in Eclipse. – opyate Nov 30 '09 at 11:13
  • 1
    @opyate You should post this as an answer as this little gem is incredibly useful. – jeckhart Oct 15 '12 at 21:29
  • You could try this instead. It won't match the inner brackets and also consider the optional`\r`.: `((?:.|\r?\n)*)` – ssc-hrep3 Nov 29 '16 at 09:52
2

Solution:

Use pattern modifier sU will get the desired matching in PHP.

Example:

preg_match('/(.*)/sU', $content, $match);

Sources:

  • The first link somehow redirects to `www.facebook.com` (which I have blocked in the [hosts file](https://en.wikipedia.org/wiki/Hosts_(file))). Is that link broken or not? – Peter Mortensen Nov 18 '21 at 23:26
  • I guess the owner decided to redirect it to the facebook page. I will remove it. – Sian Lerk Lau Nov 30 '21 at 09:29
2

In JavaScript you can use [^]* to search for zero to infinite characters, including line breaks.

$("#find_and_replace").click(function() {
  var text = $("#textarea").val();
  search_term = new RegExp("[^]*<Foobar>", "gi");;
  replace_term = "Replacement term";
  var new_text = text.replace(search_term, replace_term);
  $("#textarea").val(new_text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="find_and_replace">Find and replace</button>
<br>
<textarea ID="textarea">abcde
fghij&lt;Foobar&gt;</textarea>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Paul Chris Jones
  • 2,646
  • 1
  • 23
  • 21
1

In the context of use within languages, regular expressions act on strings, not lines. So you should be able to use the regex normally, assuming that the input string has multiple lines.

In this case, the given regex will match the entire string, since "<FooBar>" is present. Depending on the specifics of the regex implementation, the $1 value (obtained from the "(.*)") will either be "fghij" or "abcde\nfghij". As others have said, some implementations allow you to control whether the "." will match the newline, giving you the choice.

Line-based regular expression use is usually for command line things like egrep.

nsayer
  • 16,925
  • 3
  • 33
  • 51
1

Try: .*\n*.*<FooBar> assuming you are also allowing blank newlines. As you are allowing any character including nothing before <FooBar>.

hafiz031
  • 2,236
  • 3
  • 26
  • 48
  • 1
    It doesn't look right. Why two times "`.*`"? This may work for the sample input in the question, but what if "" is on line 42? – Peter Mortensen Nov 19 '21 at 00:27
1

I had the same problem and solved it in probably not the best way but it works. I replaced all line breaks before I did my real match:

mystring = Regex.Replace(mystring, "\r\n", "")

I am manipulating HTML so line breaks don't really matter to me in this case.

I tried all of the suggestions above with no luck. I am using .NET 3.5 FYI.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Slee
  • 27,498
  • 52
  • 145
  • 243
0

Often we have to modify a substring with a few keywords spread across lines preceding the substring. Consider an XML element:

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>81</PercentComplete>
</TASK>

Suppose we want to modify the 81, to some other value, say 40. First identify .UID.21..UID., then skip all characters including \n till .PercentCompleted.. The regular expression pattern and the replace specification are:

String hw = new String("<TASK>\n  <UID>21</UID>\n  <Name>Architectural design</Name>\n  <PercentComplete>81</PercentComplete>\n</TASK>");
String pattern = new String ("(<UID>21</UID>)((.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
String replaceSpec = new String ("$1$2$440$6");
// Note that the group (<PercentComplete>) is $4 and the group ((.|\n)*?) is $2.

String iw = hw.replaceFirst(pattern, replaceSpec);
System.out.println(iw);

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>40</PercentComplete>
</TASK>

The subgroup (.|\n) is probably the missing group $3. If we make it non-capturing by (?:.|\n) then the $3 is (<PercentComplete>). So the pattern and replaceSpec can also be:

pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")

and the replacement works correctly as before.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

I wanted to match a particular if block in Java:

   ...
   ...
   if(isTrue){
       doAction();

   }
...
...
}

If I use the regExp

if \(isTrue(.|\n)*}

it included the closing brace for the method block, so I used

if \(!isTrue([^}.]|\n)*}

to exclude the closing brace from the wildcard match.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Spangen
  • 4,420
  • 5
  • 37
  • 42
0

Typically searching for three consecutive lines in PowerShell, it would look like:

$file = Get-Content file.txt -raw

$pattern = 'lineone\r\nlinetwo\r\nlinethree\r\n'     # "Windows" text
$pattern = 'lineone\nlinetwo\nlinethree\n'           # "Unix" text
$pattern = 'lineone\r?\nlinetwo\r?\nlinethree\r?\n'  # Both

$file -match $pattern

# output
True

Bizarrely, this would be Unix text at the prompt, but Windows text in a file:

$pattern = 'lineone
linetwo
linethree
'

Here's a way to print out the line endings:

'lineone
linetwo
linethree
' -replace "`r",'\r' -replace "`n",'\n'

# Output
lineone\nlinetwo\nlinethree\n
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
js2010
  • 23,033
  • 6
  • 64
  • 66
-1

Option 1

One way would be to use the s flag (just like the accepted answer):

/(.*)<FooBar>/s

Demo 1

Option 2

A second way would be to use the m (multiline) flag and any of the following patterns:

/([\s\S]*)<FooBar>/m

or

/([\d\D]*)<FooBar>/m

or

/([\w\W]*)<FooBar>/m

Demo 2

RegEx Circuit

jex.im visualizes regular expressions:

enter image description here

Emma
  • 27,428
  • 11
  • 44
  • 69