Search code examples
bashsed

How to insert an autoincremented variable when replacing content in file


My goal is to insert id=“#” near every found “match” string when parsing a file. Instead of # must be an incrementing number. There are plenty of files that need to be parsed.

I’ve tried:

counter=0
find -type f -name "*.html" | xargs sed -i “s/match/id=$((++counter)) match/g”

But counter is always 1. (In addition, it would be good to set counter to 0 at the beginning of the new file, but most important is just to make it incremented).

UPDATED: I understood that provided info was not enough. It might be hundreds of files, each of them - an html document. The line of one file may look like this:

<td><span>1.6.</span><span style="background-color:#FFC1C1">2</span>

The match I'm looking for is "background-color:#FFC1C1". There also might be hundreds of those matches per ONE file. An expected result is:

<td><span>1.6.</span><span id=1 style="background-color:#FFC1C1">2</span>
/* more html here */
<td><span>Version</span><span id=2 style="background-color:#FFC1C1">4</span>
/* more html here */
<td><span>2.0.9</span><span id=3 style="background-color:#FFC1C1">2</span>
/* more html here */

But what I have now is:

<td><span>1.6.</span><span id=1 style="background-color:#FFC1C1">2</span>
/* more html here */
<td><span>Version</span><span id=1 style="background-color:#FFC1C1">4</span>
/* more html here */
<td><span>2.0.9</span><span id=1 style="background-color:#FFC1C1">2</span>
/* more html here */

Solution

  • This might work for you (GNU sed & shell):

    sed -Ei '/style="background-color:#FFC1C1".*/!b
             s//id=\n &/
             x;s/.*/echo $((&+1))/e;x
             G;s/\n(.*)\n(.*)/\2\1/' file1 file2 file3 filen
    

    Set the extended regexp option -E and replace amended file inline option -i.

    Unless a line contains style="background-color:#FFC1C1" we are not interested.

    Prepend id=, a newline (as a marker for the counter) and a space before the style attribute.

    Swap to the hold space and increment the current counter, then swap back to the pattern space.

    Append the counter to the current line and using pattern matching insert the counter where the marker was already placed.

    N.B. The -i ensures the counter will be reset for each file encountered.