Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

multiline regexp matching in bash

I would like to do some multiline matching with bash's =~

#!/bin/bash
str='foo = 1 2 3
bar = what about 42?
boo = more words
'
re='bar = (.*)'
if [[ "$str" =~ $re ]]; then
        echo "${BASH_REMATCH[1]}"
else
        echo no match
fi

Almost there, but if I use ^ or $, it will not match, and if I don't use them, . eats newlines too.

EDIT:

sorry, values after = could be multi-word values.

like image 462
pihentagy Avatar asked Sep 27 '12 10:09

pihentagy


People also ask

What is multiline matching?

Multiline option, it matches either the newline character ( \n ) or the end of the input string. It does not, however, match the carriage return/line feed character combination.

How do you do multi line grep?

Let's break this command down: The -P option enables the PCRE add-on for grep. The -z option treats the matched text as a sequence of lines by adding the NUL character to each line's ending. The -o option enables grep to print only the matched text and ignore trailing spaces.

What is Bash_rematch?

$BASH_REMATCH is an array and contains the matched text snippets. ${BASH_REMATCH[0]} contains the complete match. The remaining elements, e.g. ${BASH_REMATCH[1]} , contain the portion which were matched by () subexpressions.

What does this regex do?

Short for regular expression, a regex is a string of text that lets you create patterns that help match, locate, and manage text. Perl is a great example of a programming language that utilizes regular expressions. However, its only one of the many places you can find regular expressions.


1 Answers

I could be wrong, but after a quick read from here, especially Note 2 at the end of the page, bash can sometimes include the newline character when matching with the dot operator. Therefore, a quick solution would be:

#!/bin/bash
str='foo = 1
bar = 2
boo = 3
'
re='bar = ([^\
]*)'
if [[ "$str" =~ $re ]]; then
        echo "${BASH_REMATCH[1]}"
else
        echo no match
fi

Notice that I now ask it match anything except newlines. Hope this helps =)

Edit: Also, if I understood correctly, the ^ or $ will actually match the start or the end (respectively) of the string, and not the line. It would be better if someone else could confirm this, but it is the case and you do want to match by line, you'll need to write a while loop to read each line individually.

like image 155
Janito Vaqueiro Ferreira Filho Avatar answered Oct 10 '22 17:10

Janito Vaqueiro Ferreira Filho