6

Consider this sample file (line numbers are for reference only):

1 Reference duiarneutdigane uditraenturida enudtiar.
2
3 Reference uiae uiaetrtdnsu iatdne uiatrdenu diaren uidtae
4 on line 23.
5
6 uiae
7
8 uaiernd Reference uriadne udtiraeb unledut iaeru uilaedr
9 uiarnde line 234.

I was hoping to match every string beginning with “Reference” and ending with a period (i.e. ll. 1, 3–4, and 8–9) using this grep command (tst is the sample file):

grep -P '(?s)Reference.*?\.' tst

However, it only matches the first line. What I was thinking:

  • (?s), so . matches all characters, including newlines
  • .*? should make the star non-greedy, so it doesn’t match the whole file if it ends with a period.
  • The expression should end with a literal period \..

I’ve also tried awk and grep’s -z flag, but with both I get either every line or not all lines match my expressions.

2
  • IMHO pcregrep -M is more suitable than trying to force grep to do multiline matches using -z Feb 18, 2017 at 23:27
  • This may be the case. I haven’t tested because pcregrep is not installed on my machine by default and I’m reluctant to install new software if I need it in just one tiny script. With vatsug’s help I’ve found a solution that fits my needs.@steeldriver
    – bleistift2
    Feb 19, 2017 at 11:51

1 Answer 1

4

You can use this:

grep -Pzo '(?s)Reference.*?\.' tst.txt

where tst.txt is your input file. It is the same regex as yours, but with two new flags.

I added the -z flag to suppress newline at the end of line, substituting it for null character. Thus grep knows where end of line is, but sees the input as one big line.

The -o flag means that it only prints the matched part.

I got the following output:

Reference duiarneutdigane uditraenturida enudtiar.
Reference uiae uiaetrtdnsu iatdne uiatrdenu diaren uidtae
on line 23.
Reference uriadne udtiraeb unledut iaeru uilaedr
uiarnde line 234.
3
  • That’s definetly helpful. Thanks! I’m still somewhat unhappy with all linebreaks being gone in the output, though. Is there a way to reinsert them (e.g. at “…line 23.Reference…”), so all occurences of “Reference” start at a new line? What I get is this: Reference duiarneutdigane uditraenturida enudtiar.Reference uiae uiaetrtdnsu iatdne uiatrdenu diaren uidtae <newline> on line 23.Reference uriadne udtiraeb unledut iaeru uilaedr uiarnde line 234.
    – bleistift2
    Feb 19, 2017 at 10:13
  • @bleistift2, with -z the output terminator is also \0 (the null char); several unix commands alsa have a -z to define that input or output is null separated.
    – JJoao
    Feb 19, 2017 at 10:56
  • 1
    With some more try’n’error I found this really simple solution: grep -zoP '(?s)Reference.*?\.\n?' tst. By matching the \n at the end of the line, I get line breaks in the output: Reference duiarneutdigane uditraenturida enudtiar.<newline> Reference uiae uiaetrtdnsu iatdne uiatrdenu diaren uidtae <newline> on line 23. <newline> Reference uriadne udtiraeb unledut iaeru uilaedr <newline> uiarnde line 234. The ending line break needs to be optional, else the last line wouldn’t match, since there is no newline preceding the end of file. Thank you for your help @JJoao and vatsug
    – bleistift2
    Feb 19, 2017 at 11:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .