Bash Script to append classes to html file
If you want a general solution, you should use an html-specific tool. If you know that your html is limited to the format that you show, then try:
awk '/<\/table>/{i--} /<table>/{sub(/<table>/, "<table class=\"table"++i"\">")} 1' file.html
Example
$ awk '/<\/table>/{i--} /<table>/{sub(/<table>/, "<table class=\"table"++i"\">")} 1' file.html <table class="table1"> <tr> <td> <table class="table2"> <tr> <td> <table class="table3"> ... </table> </td> </tr> </table> </td> </tr> </table>
How it works
/<\/table>/{i--}
For any line that contains
</table>
, we decrement variablei
./<table>/{sub(/<table>/, "<table class=\"table"++i"\">")}
For any line that contains
<table>
, we increment variablei
and substitute in<table>
with the class value.1
This is awk's cryptic shorthand for print-the-line.
Changing the file in-place
If you want to change the file in-place and you have GNU awk (gawk), then use:
awk -i inplace '/<\/table>/{i--} /<table>/{sub(/<table>/, "<table class=\"table"++i"\">")} 1' file.html
For other awk:
awk '/<\/table>/{i--} /<table>/{sub(/<table>/, "<table class=\"table"++i"\">")} 1' file.html >tmp && mv tmp file.html
As a bash script
#!/bin/bash# Usage: script.sh infile outfileawk '/<\/table>/{i--} /<table>/{sub(/<table>/, "<table class=\"table"++i"\">")} 1' "$1" >"$2"
Note that the file names, $1
and $2
, are inside double-quotes. This prevents surprises in case the names contain whitespace or other shell-active characters.
As a matter of style, not substance, some people prefer spreading out awk code over multiple lines. This can make it easier to understand the code or to modify the code when one wants to add new features. Thus, if one likes, the above script can also be written as:
#!/bin/bash# Usage: script.sh infile outfileawk ' /<\/table>/{ i-- } /<table>/{ sub(/<table>/, "<table class=\"table"++i"\">") } 1 ' "$1" >"$2"
To address why your script is not working: for X in Y
splits on whitespace, not only newlines like you're expecting.
Set $IFS
to newline and it should work as intended.
#!/bin/bashIFS=''strng="<table"index=1for entry in `grep -n $strng $1`do line=`echo $entry | awk -F":" '{print$1}'` sed -e "$line s/$strng/$strng class=\"table$index\"/" -i $1 index=$(($index + 1))done
Otherwise your grep command is returning:
1: <table> 4: <table>7: <table>
and processing in 6 iterations:
1:<table>4:<table>7:<table>
You can see this by adding set -x
to the top of your script to get a trace of the commands.
Just to give a quick solution:
#!/bin/bashtemp_file="$( mktemp )"sed 's/\(<table\)/\1 class="$_field_$"/g' "$1" > "$temp_file"index=0while grep -e '[$]_field_[$]' "$temp_file" >/dev/null do sed -i "s/[$]_field_[$]/$index/" "$temp_file" ((++index)) donecp "$temp_file" "$1"rm -f "$temp_file"
But it has to be mentioned that manipulation of XML attributes should not be done using tools like sed
or awk
. Use a purpose-built tool as suggested in this answer.