4

I'm creating a Bash shell script to do some file manipulation on some HTML files.

Among the many actions I do, I have this sed command which works great:

find $DIR -type f -name '*.html' -exec sed -i 's/.*<script type="text\/javascript" charset="utf-8" src="file.js"><\/script>.*/<script type="text\/javascript" charset="utf-8" src="file2.js"><\/script>/g' {} \;

It looks through every HTML file in the directory in question, and replaces one line of text.

I wanted to do something similar where I replace multiple lines between two HTML coments.

So I want to take this:

<!-- STARTREPLACE1 -->
Blah
Blah
Blah
<!-- ENDREPLACE1 -->

And change it to:

<!-- STARTREPLACE1 -->
A whole new world!
<!-- ENDREPLACE1 -->

I found this awk command which seems to work when I run it on one file:

awk '/<!-- STARTREPLACE1 -->/{p=1;print;print "A whole new world!"}/<!-- ENDREPLACE1 -->/{p=0}!p' justonefile.html

So I thought I could do the same find function I use with sed and apply that method here in order to run this awk command on every HTML file in the directory:

find $DIR -type f -name '*.html' -exec awk '/<!-- STARTREPLACE1 -->/{p=1;print;print "A whole new world!"}/<!-- ENDREPLACE1 -->/{p=0}!p'

But when I run it, it says:

find: `-exec' no such parameter

Is there a way I can get my awk command to run on all the HTML files?

Bonus question: Can I also remove the two tags around the text I want to replace? So <!-- STARTREPLACE1 --> and <!-- ENDREPLACE1 --> are removed and I only end up with:

A whole new world!
8

First of all, you need to end the -exec action with {} \;.

Second, awk do not modify the file in place as sed do (with the -i option), so you should send the output to a temporary file, then move this to the original file.

Create a script (say we call it replace) with the following content:

#!/bin/sh
tfile=$(mktemp)
awk '/<!-- STARTREPLACE1 -->/{p=1;print;print "A whole new world!"} 
     /<!-- ENDREPLACE1 -->/  {p=0}' "$1" >"$tfile" && \
  mv "$tfile" "$1"

give it executable permissions

chmod +x ./replace

then run

find "$DIR" -type f -iname '*.html' -exec ./replace {} \;
  • Sounds like using a temporary file is a good idea. Any chance you could explain how I do that? Or can I change awk for sed and get the same result? – Questioner Apr 2 '12 at 13:48
  • @DaveMG: I added something to my answer. – enzotib Apr 2 '12 at 14:11
  • Thanks so much for providing a method for acting on all the files. The only thing is there seems to be a bug in the code somewhere, because after running the ./replace script, all the HTML files are completely empty. Hmmm.. – Questioner Apr 2 '12 at 15:08
  • @DaveMG: yes, there was, I corrected it now. I hope you have tested it on a copy of the files. – enzotib Apr 2 '12 at 15:10
  • It works now, but only if where you have / {p=0}' is replaced by /{p=0}!p'. Thanks again so much for the code! – Questioner Apr 2 '12 at 15:55
2

And for the bonus:

gawk '{!p} /<!-- STARTREPLACE1 -->/{print "A whole new world!";p=1}/<!-- ENDREPLACE1 -->/{p=0}'
  • what is this supposed to do: {!p} ? – glenn jackman Apr 2 '12 at 13:04
  • I tested this, but it doesn't seem to do anything. – Questioner Apr 2 '12 at 15:57
  • errata - should be gawk '!p{} /<!-- STARTREPLACE1 -->/{print "A whole new world!";p=1}/<!-- ENDREPLACE1 -->/{p=0}' but it works for me with both syntax. Dave what do you mean Is doesn't do anything? Which awk version are you using? – Eran Ben-Natan Apr 4 '12 at 4:47

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.