3

So what I would need is for grep to match only the text in between (and including) my match pattern.

So something like this (don't mind the text, it's just some garble :D):

asdgfasd gasd gdas g This will be this one day ksjadnbalsdkbgas asd gasdg 
asdgasdgasdg dasg dasg dasg This will be this next day adf gdsf gdsf sdfh dsfhdfsh
asdf asdf asd fesf dsfasd f This will won' not this day asdgadsgaseg as dvf as d vfa se v asd
dasfasdfdas fase fasdfasefase fasdf This not what shoes day asdjbna;sdgbva;sdkbcvd;lasb ;lkbasi hasdli glais g

So what I want is something like this: cat theabovetext|grep -E "^This * day$" To output this:

This will be this one day
This will be this next day
This will won' not this day
This not what shoes day

So basically I want to ONLY get the text in between This and Day (including This and day) regardless of how many characters there are in between, and regardless of how many characters there are before This and after Day. Also this needs to work even if the input is all on a single line, so this:

asdgfasd gasd gdas g This will be this one day ksjadnbalsdkbgas asd gasdg asdgasdgasdg dasg dasg dasg This will be this next day adf gdsf gdsf sdfh dsfhdfsh asdf asdf asd fesf dsfasd f This will won' not this day asdgadsgaseg as dvf as d vfa se v asd dasfasdfdas fase fasdfasefase fasdf This not what shoes day asdjbna;sdgbva;sdkbcvd;lasb ;lkbasi hasdli glais g

Has to output this:

This will be this one day This will be this next day This will won' not this day This not what shoes day

N.B. the output here is still on a single line.

  • 1
    What version of grep are you looking to use? GNU with perl style regex will can do it, otherwise are you open to non-grep solutions? – Eric Renouf Jan 1 at 22:33
  • grep (GNU grep) 2.20, but if it's awk or sed, I can work with those as well – superme Jan 1 at 22:34
  • @superme I've attempted to emphasise important parts of your question. Feel free to re-edit if I have misread the question. – Sparhawk Jan 1 at 23:05
3

If you want lines to be processed separately (your first example) but for multiple matches per line to be output on a single line (as in your second example), then I don't think that's possible with grep alone.

However using the same This.*?day non-greedy match in perl itself you can do

$ perl -lne 'print join " ", /This.*?day/g' theabovetext1
This will be this one day
This will be this next day
This will won' not this day
This not what shoes day

while for the single-line input

$ perl -lne 'print join " ", /This.*?day/g' theabovetext2
This will be this one day This will be this next day This will won' not this day This not what shoes day
4

With GNU grep you could do the following:

grep -o 'This.*day' theabovetext

(note that you don't need cat since grep knows how to read files)

The -o flag says to show only the parts of the line that match the pattern.

I suspect other versions of grep support this flag as well, but it's not in POSIX, so it's not portable necessarily.

  • 1
    [me@there ~]$ grep -o 'This.*day' theabovetext This will be this one day ksjadnbalsdkbgas asd gasdg asdgasdgasdg dasg dasg dasg This will be this next day adf gdsf gdsf sdfh dsfhdfsh asdf asdf asd fesf dsfasd f This will won' not this day asdgadsgaseg as dvf as d vfa se v asd dasfasdfdas fase fasdfasefase fasdf This not what shoes day it only removes the first part and the last part of the gibberish it doesn't remove it in between matches – superme Jan 1 at 22:43
  • 3
    You can use PCRE mode so that the quantifier can be made non-greedy grep -oP 'This.*?day' theabovetext however this will place each match on a separate line in both cases – steeldriver Jan 1 at 22:51
  • @steeldriver that worked, thanks! I can't select your comment as the right answer though. One thing I'd like to know though: how come with 'This.*day' it doesn't match it, but adding the ? matches it? – superme Jan 1 at 23:19
  • @superme I didn't post it as an answer because I don't believe it satisfies your requirement that "the output here is still on a single line" for the case where the input is on a single line – steeldriver Jan 1 at 23:22
  • 1
    @superme it modifies the * to make it non-greedy - see for example Perl regex tutorial: non-greedy expressions – steeldriver Jan 1 at 23:41
0

Eric Renouf's response does most of the work. And steeldriver's comment cuts out the extra text within a given line by making it non-greedy.

So it seems like: grep -oP 'This.*?day' theabovetext does everything you want except the output is on multiple lines.

To put the output on one line you could do grep -oP 'This.*?day' theabovetext | tr '\n' ' '. This addition simply replaces newline breaks with spaces*

*This will replace all output newlines with spaces. So if your initial input is line separated, these newline breaks will be lost.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.