Sed заменяет каждое n-е вхождение

Я пытаюсь использовать sed для замены любого другого элемента html файла, чтобы я мог создавать чередующиеся строки цвета.

Вот что я пробовал, и он не работает.

sed 's/<tr valign=top>/<tr valign=top bgcolor='#E0E0E0'>/2' untitled.html

Ответ 1

Я бы решил это с awk:

awk '/<tr valign=top>/&&v++%2{sub(/<tr valign=top>/, "<tr valign=top bgcolor='#E0E0E0'>")}{print}' untitled.html 

Сначала он проверяет, содержит ли строка <tr valign=top>

/<tr valign=top>/&&v++%2

и является ли <tr valign=top> нечетным найденным экземпляром:

v++%2

Если это так, он заменяет <tr valign=top> в строке

{sub(/<tr valign=top>/, "<tr valign=top bgcolor='#E0E0E0'>")}

Поскольку все строки должны быть напечатаны, есть блок, который всегда будет выполняться (для всех строк) и будет печатать текущую строку:

{print}

Ответ 2

Это работает для меня:

sed -e "s/<tr/<TR bgcolor='#E0E0E0'/g;n" simpletable.htm

ввод образца:

<table>
  <tr><td>Row1 / col1</td><td>col2</td><td>col3</td></tr>
  <tr><td>Row2 / col1</td><td>col2</td><td>col3</td></tr>
  <tr><td>Row3 / col1</td><td>col2</td><td>col3</td></tr>
  <tr><td>Row4 / col1</td><td>col2</td><td>col3</td></tr>
  <tr><td>Row5 / col1</td><td>col2</td><td>col3</td></tr>
</table>

вывод образца:

<table>
  <TR bgcolor='#E0E0E0'><td>Row1 / col1</td><td>col2</td><td>col3</td></tr>
  <tr><td>Row2 / col1</td><td>col2</td><td>col3</td></tr>
  <TR bgcolor='#E0E0E0'><td>Row3 / col1</td><td>col2</td><td>col3</td></tr>
  <tr><td>Row4 / col1</td><td>col2</td><td>col3</td></tr>
  <TR bgcolor='#E0E0E0'><td>Row5 / col1</td><td>col2</td><td>col3</td></tr>
</table>

Ключ должен использовать команду n в sed, которая продвигается к следующей строке. Это работает только в том случае, если TR занимают отдельные строки. Он будет разбит на вложенные таблицы или если в одной строке несколько TR.

Ответ 3

Согласно http://www.linuxquestions.org/info/programming-9/replace-2nd-occurrence-of-a-string-in-a-file-sed-or-awk-800171/

Попробуйте это.

sed  '0,/<tr/! s/<tr/<TR bgcolor='#E0E0E0'/' file.txt

Восклицательный знак отменяет все с начала файла на первый "Джек", так что подстановка работает на всех следующих строках. Обратите внимание: я считаю, что это только операция gnu sed.

Если вам нужно использовать только второе вхождение и игнорировать любые последующие совпадения, вы можете использовать вложенное выражение.

sed  '0,/<tr/! {0,/<tr/ s/<tr/<TR bgcolor='#E0E0E0'/}' file.txt

Здесь выражение в скобках будет работать на выходе первой части, но в этом случае оно выйдет после изменения первого совпадающего "Jack".

PS, я нашел sed faq, чтобы быть очень полезным в таких случаях.