1

Does anyone know a shell command (egrep,grep) to find a match over multiple lines?

Here is part of my data:

/id D4333F9F; Fri, 23 Mar 2018 16:12:13 -0300 (-03)^M
Subject: =?UTF-8?Q?(Observado)=20[Chamado=202223936]=20-=20?=  =?UTF-8?Q?> Configura=C3=A7=C3=A3o=20DNS?=^M
Date: Fri, 23 Mar 2018 16:12:13 -0300^M
Content-Type: text/html; charset=UTF-8^M
Content-Transfer-Encoding: quoted-printable^M
Content-Disposition: inline^M
MIME-Version: 1.0^M

Inside my bash over here, i have tried to find an expression: `

/id D4333F9F.*

(Pay attention at the .* regular expression to select everything until the end of the file)

The command inserted on the window is simulating a grep command, but my search stopped at ^M character

I would like to continue searching until the MIME-Version of the header mail (this is an Thunderbird file).

John1024
  • 109,961
  • 14
  • 137
  • 171
  • 1
    Sorry, i will edit to go over better – Bruno Minossi Jul 04 '18 at 21:37
  • Do you have a space between `.` and `*` in the regexp? It doesn't look like it in the image, but that's what you put in the question. – Barmar Jul 04 '18 at 21:38
  • 1
    `grep` operates on a single line at a time. The `^M` are all at the end of the lines, they're Windows `CRLF` newlines. – Barmar Jul 04 '18 at 21:39
  • you can't use `grep` to match across multiple lines. – Barmar Jul 04 '18 at 21:39
  • 1
    Use Control-k to mark formatted text, so it won't be re-wrapped by the SO editor. – Barmar Jul 04 '18 at 21:40
  • 1
    You keep mentioning a "bash", I assume you mean a bash script. You need to post the script you're having trouble with, not an image of a `vim` session. – Barmar Jul 04 '18 at 21:41
  • @Barmar yes, i've replaced my image to code for i dont do more mistakes – Bruno Minossi Jul 04 '18 at 21:41
  • 1
    The replacement doesn't have the line breaks. – Barmar Jul 04 '18 at 21:42
  • If using grep and the id is not broken by CRLF, just use `/id D4333F9F`. Grep can search anywhere, returns the entire line it found the substring. –  Jul 04 '18 at 21:44
  • @sln i'm trying to get everything after the id expression, but the windows carriege is stopping my search :-/ I describe the problem using vim editor because i think that the command in the terminal linux will not help us.: minossi@CW000683:~/.thunderbird/9jmr3uzb.default$ egrep -rn "id D4333F9F.*" ~/.thunderbird/*.default/ImapMail/imap*/INBOX*/[Observado]* – Bruno Minossi Jul 04 '18 at 21:47
  • If you're trying to get to the end of file, unless grep has slurp capability, but wouldn't be grep then. If running from a script, don't use grep. But if you have to, then find where the first grep find is. Then catenate with a separate grep `.+` all the lines after. –  Jul 04 '18 at 21:55
  • How can i change this topic as solved? I had never imagined that grep cant across multiple lines :| – Bruno Minossi Jul 04 '18 at 22:04

1 Answers1

1

To simplify, lets consider this file:

$ cat file
before
/id D4333F9F 1234
another line
last line in file

The problem that you are running into is not ^M. It is that standard grep processes only one line at a time.

Using sed

To get everything from the line containing /id D4333F9F to the end of the file, there are several standard tools that you can use. For example, try sed:

$ sed -n '/\/id D4333F9F/,$ p' file
/id D4333F9F 1234
another line
last line in file

Here /\/id D4333F9F/,$ p tells sed to print any lines starting with a line matching /id D4333F9F and ending with the last line ($).

Using awk

Try awk:

$ awk '/\/id D4333F9F/{f=1} f' file
/id D4333F9F 1234
another line
last line in file

Here, /\/id D4333F9F/{f=1} tells awk to set the variable f to one when the first line that matches /id D4333F9F is found. The last f is shorthand that tells awk to print if f is true (meaning nonempty or nonzero).

Using grep with GNU extensions

Lastly, if your grep has the -P extension (this requires GNU grep), then try:

$ grep -ozP '(?s)/id D4333F9F.*' file
/id D4333F9F 1234
another line
last line in file

This grep code is explained in detail here.

John1024
  • 109,961
  • 14
  • 137
  • 171