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 Sep 18 '15 at 9:36

[^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 Sep 18 '15 at 10:09
  • How is -E different from -r, i thought it was just the OSX version? – 123 Sep 18 '15 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. – Stéphane Chazelas Sep 18 '15 at 13:22

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.