I'm getting stuck with sed.. I'm trying to prefix links in an html file with a / when they don't start with http.. I'm aware this is possibly not the best way to go about this but I'm just after a simple quick/solution.

So far, I've tried this (note IRL I'll use the -i in place flag etc, this is just for testing):

echo '<a href="egww">blah</a><a href="http://bloge.weg">yeah</a>' |
sed 's@href="[^http]@href="/@g'

This almost works:

<a href="/gww">blah</a><a href="http://bloge.weg">yeah</a>

Except the first character of the first link has got cut off, also I think it's not not matching on h,t,t or p rather than the entire string http:

echo '<a href="egww">blah</a><a href="p/bloge.weg">damn</a>' |
sed 's@href="[^http]@href="/@g'

<a href="/gww">blah</a><a href="p/bloge.weg">damn</a>

I'm pretty stumped at this point, unfortunately google doesn't help much here as negation with sed is generally used for removing lines that contain a string rather than not matching substrings in lines.. I tried several 'normal' regexp patterns but these don't seem to work.

Any ideas?

  • Apologies for the double negative :p
    – John Hunt
    Commented Sep 18, 2015 at 9:36

1 Answer 1


[^http] is not anything but http. That RE matches one character as long as it's neither h, nor t, nor p. So href="[^http] matches href="b in href="blah", but not href="t in href="toto".

Here, you'd want something like:

sed -E 's@(href=")([^h]|h([^t]|t([^t]|t([^p]|$)|$)|$)|$)@\1/\2@g'

That is href=" followed by either not-h (a character other than h), or h-not-t, or ht-not-t, or htt-not-p, or htt-EOL, or ht-EOL or h-EOL or EOL. (EOL == "end of line", those last 4 unlikely to be found in the input as that would mean the " is not matched).

(assuming your sed supports the not-yet-standard -E option).

You could also add the / always but remove it after when in href="/http:

sed 's@href="@&/@g;s@href="/http@href="http@g'

Or with perl:

perl -pe 's|href="\K(?!http)|/|g'

Using perl's negative look-ahead RE operator.

  • I didn't really understand most of your answer, but the idea of using sed twice worked! That is also much easier to understand :) Thanks!
    – John Hunt
    Commented Sep 18, 2015 at 10:09
  • How is -E different from -r, i thought it was just the OSX version?
    – 123
    Commented Sep 18, 2015 at 13:18
  • 1
    @User112638726, -r is the GNU (inexplicable) variant. -E is supported by FreeBSD, OS/X and GNU and scheduled for inclusion in the next major version of the POSIX/Unix spec. Commented Sep 18, 2015 at 13:22

You must log in to answer this question.

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