7

I have a file with pattern

    <span class="WebRupee">Rs.</span>\n29\n<br/><font style="font-size:smaller;font-weight:normal">\n3 days\n</font></td>, <td class="pricecell"><span class="WebRupee">Rs.</span>\n59\n<br/><font style="font-size:smaller;font-weight:normal">\n7 days\n</font></td>, <td class="pricecell"><span class="WebRupee">Rs.</span>\n99\n<br/><font style="font-size:smaller;font-weight:normal">\n12 days\n</font></td>

I want the values 29, 3 days, 59 etc.

basically the value between \n value \n

I have consulted many places but I do not know how to escape the \n characters.

I have tried :- grep -o '\n.*\n' o.txt But it did not work

  • Don't parse XML or HTML with regular expressions. It doesn't work reliably. – cas Jul 24 '16 at 13:01
  • From the link you just posted. ... but I think that's just as wrongheaded as demanding every trivial HTML processing task be handled by a full-blown parsing engine.. It's not a crime to use a regular expression to get some text from a file. I've heard so many people preach that you should not do it, but there is absolutely nothing wrong with doing it on a small scale if you know what you're doing. – Klik Jul 29 '16 at 3:52
  • 1
    it's not a crime, but it's never a good idea to create fragile scripts. all it takes is one minor change in the XML or HTML data, and your regexp extraction will break. using a parser will cope with changes just fine. so, creating fragile programs is wrong - something that only works sometimes is broken. btw, it's not only about whether you "know what you are doing", it's mostly about the fact that you can't be certain that the XML/HTML data won't change. also, most people who think they know what they're doing don't. – cas Aug 4 '16 at 10:22
9

Grep interprets \n as a newline character. It looks like your file does not have newline characters, it has \ followed by n. To search for literal backslashes, you must double them:

$ grep -o '\\n[^\\]*\\n' o.txt
\n29\n
\n3 days\n
\n59\n
\n7 days\n
\n99\n
\n12 days\n

With GNU grep, the output can be easily cleaned up to remove the \n:

$ grep -oP '(?<=\\n)[^\\<>]*(?=\\n)' o.txt
29
3 days
59
7 days
99
12 days

Here, (?<=\\n) is a look-behind assertion and (?=\\n) is a look-ahead assertion to require that the text that we match be surrounded by \n. While grep returns non-overlapping matches, a subtlety here is that the look-behinds and look-aheads are not counted toward the match. This leaves us with the issue that the text that we don't want is also surrounded by \n. For example, in o.txt, the characters \n<br/><font style="font-size:smaller;font-weight:normal">\n are surrounded by \n. To eliminate these strings, we require that the matching text exclude not just \ but also < and >.

If we don't have GNU grep, another option is to use sed to clean up the output:

$ grep -o '\\n[^\\]*\\n' o.txt | sed 's/\\n//g'
29
3 days
59
7 days
99
12 days

Another option is to use awk:

$ awk '0==NR%2' RS='\\\\n' o.txt
29
3 days
59
7 days
99
12 days

Here, awk is using \ followed by n as the record separator and we print only the even numbered records.

  • this works, but i get output with \n also, how to get just the values ? – penta Jul 23 '16 at 20:59
  • Cool. Can you explain what [^\\<>]* does in 2nd grep expression ? – Rahul Jul 23 '16 at 21:09
  • @Rahul That one is quite subtle. I just updated the answer with an explanation. – John1024 Jul 23 '16 at 21:48

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.