Использование sed для добавления строки к четвертому вхождению шаблона - PullRequest
1 голос
/ 16 февраля 2012

Я разрабатываю патч bash для выполнения нескольких операций с простыми текстовыми файлами, чтобы уменьшить количество ручных правок на нескольких веб-серверах. Одна часть, которая выходит за рамки моих знаний о sed, - это то, как я буду редактировать строку, которая встречается более одного раза, только редактируя одно из конкретных случаев. Возьмите следующий отредактированный HTML, например:

<div class="dashlet">
  <div class="body">
    <div class="detail-list-item">
      <!-- some content here -->
    </div>
    <div class="detail-list-item">
      <!-- some more content here -->
    </div>
    <div class="detail-list-item">
      <!-- some more content here -->
    </div>
    <div class="detail-list-item">
      <!-- some more content here -->
    </div>
    <div class="detail-list-item last-item">
      <!-- some final content here -->
    </div>
  </div>
</div>

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

sed -i '29,33d' /path/to/file

Где 29 - строка, в которой включена <div class="detail-list-item last-item">, а 33 - соответствующий закрывающий тег </div>. Есть ли лучший способ сделать это, чтобы предотвратить будущие обновленные версии этого файла, чтобы мне не пришлось проверять файл, чтобы убедиться, что я не удаляю неправильные строки?

Последняя часть состоит в том, что мне нужно заменить предыдущий html-класс, чтобы включить last-item в качестве второго класса. Таким образом, окончательный HTML будет выглядеть так:

<div class="dashlet">
  <div class="body">
    <div class="detail-list-item">
      <!-- some content here -->
    </div>
    <div class="detail-list-item">
      <!-- some more content here -->
    </div>
    <div class="detail-list-item">
      <!-- some more content here -->
    </div>
    <div class="detail-list-item last-item">
      <!-- some final content here -->
      <!-- note how we are one div shorter and this div's class has a second class -->
    </div>
  </div>
</div>

Какие команды sed могут выполнить эту задачу?

1 Ответ

2 голосов
/ 16 февраля 2012

Поскольку sed обрабатывает файл построчно, это может быть не лучшим решением для этого.Однако, так как ваш файл довольно мал, вы можете использовать это несколько хакерское решение, которое помещает весь файл в буфер хранения, а затем выполняет подстановку всего файла сразу:

sed -rni 'H;${x;s/\n(.*list-item)(".*)\n    <div.*    <\/div>/\1 last-item\2/p}' /path/to/file

Вот объяснение:

# options: -r  extended regex so parentheses don't need to be escaped
#          -n  don't automatically print pattern space
#          -i  edit file in place
H;                     # add the current line to the hold space
$                      # if we are at the last line
  {                    # commands until '}' are only run if at the last line
    x;                 # swap pattern space and hold space
    s/                 # search/replace
      \n(.*list-item)  # greedy match to the last 'list-item', put in group 1
      (".*)            # double quote must follow 'list-item', match as many
                       # characters as possible and put in group 2
      \n    <div.*    <\/div>    # match all of the next (final) double-indented
                                 # div, don't put it in a group
     /
      \1 last-item\2   # insert ' last-item' before groups 1 and 2, final 
                       # double-indented div will be deleted
     /p                # print the result
  }

Вы можете выполнить часть, в которой удаляете последний div, с помощью гораздо более простой команды:

sed -i '/<div.*last-item/,/<\/div>/d' /path/to/file

К сожалению, я не знаю простого способа добавления last-itemкак второй класс до окончательного div.

...