Bash Script to append classes to html file Bash Script to append classes to html file shell shell

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

  1. /<\/table>/{i--}

    For any line that contains </table>, we decrement variable i.

  2. /<table>/{sub(/<table>/, "<table class=\"table"++i"\">")}

    For any line that contains <table>, we increment variable i and substitute in <table> with the class value.

  3. 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.