4

I use the same regex with grep and it gives me a match but when doing it in a bash script, it return no match.

Test String(part of the file testregex.txt):

<a href="/os_x_lynx-wallpapers.html"><p>OS X Lynx</p><img src="/thumbs/os_x_lynx-t1.jpg"alt="OS X Lynx" class="thumb_img" width="270" height="169"/></a></div><div style="float:right;margin-right:13px;"></div></div>

This command correctly matches the highlighted part(and a few more):

grep -E '<img src="[^"]*\.jpg"' testregex.txt

But this bash script returns no match:

page=$(<testregex.txt)

if [[ $page =~ '<img src="[^"]*\.jpg"' ]]; then
    echo $1
    echo "match found"
else
    echo "match not found!"
fi
2
  • Note: the regex also works without using the -E switch for grep
    – udiboy1209
    Apr 3, 2014 at 6:43
  • Regex is a DOM-ignorant tool. A DOM parser should be used to parse valid html. Apr 22, 2020 at 9:54

2 Answers 2

4

In the case =~ operator, just don't use quotes for the right operator. This is considered an extended regular expression so in this case the single quotes will be part from he regular expression. So, using single quotes, a string like '<img src="/thumbs/os_x_lynx-t1.jpg"' (which contain also single quotes around it) will be found. See Meaning of “=~” operator in shell script.

Also, you must to escape any special character in your regex (quotes, spaces, shell redirection - <):

#!/bin/bash
page=$(<testregex.txt)

if [[ $page =~ \<img\ src=\"[^\"]*\.jpg\" ]]; then
    echo $1
    echo "match found"
else
    echo "match not found!"
fi

Apart of =~, you can use in your script your original command which uses grep:

#!/bin/bash

if grep -qE '<img src="[^"]*\.jpg"' testregex.txt ; then
    echo $1
    echo "match found"
else
    echo "match not found!"
fi

In this case I used -q option for grep to not write anything to standard output and to exit immediately if any match is found.

3
  • 1
    There's also -q so you don't have to redirect to /dev/null and it will stop grepping once a match is found, or do the redirect and use -m 1 to achieve the same result. Depending on the size of the file, it might speed things up.
    – mrjink
    Apr 3, 2014 at 9:40
  • 1
    @mrjink You have perfectly right. I forgot about -q. I edited my answer. Apr 3, 2014 at 9:47
  • Thanks for the update. I did end up using grep finally, because I wanted to perform actions on the matches and not just see if a match exists.
    – udiboy1209
    Apr 3, 2014 at 17:36
3

If you write [[ "$page" =~ '<img src="[^"]*\.jpg"' ]], then the right-hand side will be treated as an ordinary string, not a regex. See Bash regex statement. The solution is to escape all the special characters.

otherwise you can use regex statement in a separate variable within single quotes '' like,

var='<img src="[^"]*\.jpg'

in these case you do not need to escape special characters one by one.

#!/bin/bash
page=$(<testregex.txt)
var='<img src="[^"]*\.jpg'

if [[ "$page" =~ $var ]]; then
#    echo $1
    echo "match found"
else
    echo "match not found!"
fi

I have commented the echo $1 statement. Difference in single and double quotes in bash.

3
  • Could you also show me how to put a backreference in there. Just adding brackets gives me a syntax error. Should be like this var=\<img src="([^"]*\.jpg) but that stray ) gives a syntax error.
    – udiboy1209
    Apr 3, 2014 at 7:02
  • OK I got it. Using single quotes when declaring var seems to work.
    – udiboy1209
    Apr 3, 2014 at 7:15
  • @udiboy look at the edit. I think your brackets issue is also solved.
    – sourav c.
    Apr 3, 2014 at 8:38

You must log in to answer this question.

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