Description
In this example, the occurrence of every third [0-9]+ will be enclosed in a pair of brackets.
Raw Input
First number 1, Second 22, Third 333, Fourth 4444,
Fifth 555,
Sixth 66, Seventh 7, Eighth 88,
Ninth 999, Tenth 1010, Eleventh 11111, Twelfth 1212,
Thirteenth 13, Fourteenth 141414, Fifteenth 15
Desired Output
First number 1, Second 22, Third [333], Fourth 4444,
Fifth 555,
Sixth [66], Seventh 7, Eighth 88,
Ninth [999], Tenth 1010, Eleventh 11111, Twelfth [1212],
Thirteenth 13, Fourteenth 141414, Fifteenth [15]
Script and Comments
Script1
[ 1] s/[0-9]+/\n&/g
[ 2] /\n/!b
[ 3] G
[ 4] :loop
[ 5] s/$/#/
[ 6] s/#{3}$//
[ 7] /\n$/s/\n([0-9]+)/\n[\1]/
[ 8] s/\n//
[ 9] /\n.*\n/b loop
[10] P
[11] s/^.*\n//
[12] h
[13] d
Comments -r
  1. This script has to number every occurrence of [0-9]+ where the N-th occurrence is given (N mod 3)+1 as its ordinal number. In this example, the ordinal ranges from 1 to 3.
  2. Since numbering must go on from one line to the next, we have to keep in some place the ordinal number of the last occurrence of the current line for later use. That number is kept as the equivalent number of `#'s in HS.
  3. Step [1] inserts a newline character before every occurrence in a line.
  4. If a line has no occurrence, after Step [1], there will be no newline character in PS. In this case, Step [2] prints it and then starts a new cycle.
  5. Before numbering a line,
    • `G' of Step [3] appends to PS the ordinal of the last occurrence of the previous line.
    • The line is then consists of two parts: the data and the number. Two parts are separated by a newline character, and we will refer to the part containing the number as `counter'.
  6. Then the following steps will be performed on each occurrence:
    • Step [5] increases the counter by one.
    • If the value of the counter is 3, this occurrence is what we want, and Step [7] will enclose it with a pair of brackets.
      To ensure that the ordinal of the next occurrence is one, Step [6] resets the counter to zero by removing all `#'s.
    • After examine an occurrence, Step [8] removes the newline character preceding it.
    • If there exists non-examined occurrence, PS contains at least two newlines (including the one separating the data and the counter). In this case, Step [9] makes sed jump to Step [4] to examine the next occurrence.
    • Otherwise, examination on the current line finishes:
      • Step [10] print the data.
      • Step [11] removes all but the ordinal number and then Step [12] keeps it in HS.
      • `d' of Step [13] empties PS and then starts a new cycle.