is it possible to use sed to match the source of a script tag within html (which is not valid xml) and replace the whole match with the files' contents?

e.g. say the html contained

<link rel='stylesheet' href="blah.css">
<script src='foo.js'></script>
<script type="text/javascript" src="bar.js"></script>
<title />

I want to not only match 'foo.js' from within src='foo.js' but also to replace in this file the contents of foo.js, so to end up

<link rel='stylesheet' href='blah.css'>
<script>var foo = {};</script>
<script>var bar = [];</script>
<title />  

In a regex I can match the script tag src value like so:


with the match being in the second capture group.

I don't mind rewriting the whole line, but how do I get sed to match on that expression - it doesn't seem to like capture groups or backreferences (at least, the way I'm trying it: I know it does). I get an unhelpful

syntax error near unexpected token `)'

Also how can I capture the file name and then pipe its contents back in as the replacement line?

  • What is the full sed command that is giving you the error message? What version of sed are you using? – Weijun Zhou Mar 19 '19 at 12:11
  • sed on osx (so bsd); trying sed -E 's/<script\s+(?:[^>]*?\s+)?src=(["'])(.*?)\1/whatever/' file.html; trying to escape that single quote with \' or \x27 isn't happening – frumbert Mar 19 '19 at 12:41
  • Regardless of sed, you need to replace ' with '\'' when you try to write single quotes in single quoted strings. – Weijun Zhou Mar 19 '19 at 12:46
  • yes. if i reverse the quoting and escape sed -E "s/<script\s+(?:[^>]*?\s+)?src=(["'])(.*?)\1/whatever/" file.html yields RE error: repetition-operator operand invalid which is normally missing -r but -E should cover that – frumbert Mar 19 '19 at 12:58
  • * ["'] supposed to be [\"'] of course, but it still has the error – frumbert Mar 19 '19 at 13:04

I would use instead:

awk '
    match($0, "<script src=." jsfile ".></script>") {
        print "<script>"
        while (getline line < jsfile) print line
        print "</script>"
' jsfile=foo.js file.html

which outputs

<link rel='stylesheet' href="blah.css">
var foo = {};
var bar = [];
<script type="text/javascript" src="bar.js"></script>
<title />

To save the output back to the original html file:

awk ... > "$tmp" && mv "$tmp" file.html
  • great! i've heard of awk for a while but never really used it. this example provides exactly what I need to get started. Cheers! – frumbert Mar 19 '19 at 21:14
  • I started off trying to solve it with sed, but I couldn't quite get the output in the right order. – glenn jackman Mar 19 '19 at 21:42

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.