Question title may be kinda vague, but heres what im attempting to do.

I have a html file locally on my server which is changing fairly regularly. It has multiple occurrences of:

<p>Jumble of random text</p>
<p>More text</p>

And so on...

I want to be able to sort through all the different jumble of random text's till it finds the one I am looking for, for example 'random', which could be anywhere in the file. Then I want a variable assigned to

Jumble of random text

Everything between the:

<p> and </p>

So far I have this:

echo grep -i 'random' search.html | grep -o -P '(?<=<p>).*(?=</p>)' search.html

Which works to an extent, however it is finding the first occurrence and the last occurrence of the paragraph tags, therefore giving me a huge output of meaningless data, ie in this case:

Jumble of random text
More text

How can i get it to just return:

Jumble of random text

Getting very confused, very fast.

  • what about grep -o -P '(?<=<p>).*(?=</p>)' search.html| grep -i random ? – Archemar Mar 8 '15 at 10:13

This is because the match pattern .* is what is known as a greedy match, meaning that it will return the largest string to match your search pattern.

What you would want to do is to use a non-greedy (or lazy) match, which returns the shortest string to match your pattern. You can do this by changing your greedy match from .* to .*?. However, grep typically doesn't support this by default, but you can enable this by using the -P option which allows perl-like regex matching.

In short, you can change your grep command to grep -o -P '(?<=<p>).*?(?=</p>)'.

More details on this answer can be found at https://stackoverflow.com/questions/3027518/non-greedy-grep

  • Thanks for the reply, but that still doesn't work. Any ideas why? EDIT: Ahh seems like it doesnt work in some versions. I shall see what version of grep i have. – James Hiey Mar 8 '15 at 11:17
  • @JamesHiey What is the exact command you're running - in your question you've shown the command as echo cat ... which is an unusual command combination to say the least ;-) – wraeth Mar 8 '15 at 11:22
  • echo grep -i 'random' search.html | grep -o -P '(?<=<p>).*?(?=</p>)' search.html Where search.html contains: <p>Jumble of random text</p> <p>More text</p> – James Hiey Mar 8 '15 at 11:40
  • Most likely completely wrong... – James Hiey Mar 8 '15 at 11:41
  • @JamesHiey In short: yes. echo simply repeats things given to it, so in this case would send grep, -i, random and search.html through a pipe to another grep. What you would actually want is something more like grep -o -P '(?<=<p>).*(?=</p>)' search.html. This calls grep showing -only matching strings, using -Perl-like regex matching, on the file search.html. – wraeth Mar 8 '15 at 11:50

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.