#linux #shell #unix
#linux #оболочка #unix
Вопрос:
Я получил html
файл, который выглядит следующим образом (удалите некоторые ненужные слова).
<li class="toctree-l1">examples</a></li>
<li class="toctree-l3">charcnn</a></li>
<li class="toctree-l4">cifar10</a></li>
Я хочу отредактировать его, не заходя в файл ( sed
например, команда). У меня был dict
, который
dict = {'example':l1, 'charcnn':l2, 'cifar10':l3}
После dict
, html
файл должен быть
<li class="toctree-l1">examples</a></li>
<li class="toctree-l2">charcnn</a></li>
<li class="toctree-l3">cifar10</a></li>
Перед заменой это l1
, l3
и l4
. После этого l1
, l2
и l3
.
Я знаю sed
, что команда может заменяться ключевыми словами, но она используется для замены текущих слов. Есть ли способ заменить другое слово при условии слова в той же строке?
Комментарии:
1. Данные одинаковы до и после. Что нужно изменить?
2. @RamanSailopal Перед l1, l3 и l4 . После — l1, l2 и l3.
3. Awk — это возможность для этого, но она не идеальна для html / XML. Однако нам понадобится весь полный HTML-файл.
4.
html/XML
не в этом суть. Вы можете использовать его как файл другого типа (txt
например). Суть в том, можем ли мы заменить другое слово при условии слова в той же строке.5. Я не понимаю предложение «Я хочу отредактировать его, не заходя в файл (например, команда sed)». Можете ли вы перефразировать или объяснить это, особенно фразу «отредактируйте это, не заходя в файл» ?
Ответ №1:
Конечно sed
, можно заменить одну часть строки в зависимости от другой части строки.
Для вашего примера данных вы могли бы использовать
sed 's#(<li class="toctree-)[^"]*(">examples</a></li>)#1l12#
s#(<li class="toctree-)[^"]*(">charcnn</a></li>)#1l22#
s#(<li class="toctree-)[^"]*(">cifar10</a></li>)#1l32#' inputfile
Команды проверяют всю входную строку, но допускают все, что находится между toctree-
и "
.
С этим (измененным) вводом
<li class="toctree-l1">examples</a></li>
<li class="toctree-l3">charcnn</a></li>
<li class="toctree-l4">cifar10</a></li>
<li class="toctree-something">other</a></li>
<li class="toctree-foo">examples</a></li>
<li class="toctree-bar">charcnn</a></li>
<li class="toctree-baz">cifar10</a></li>
вывод
<li class="toctree-l1">examples</a></li>
<li class="toctree-l2">charcnn</a></li>
<li class="toctree-l3">cifar10</a></li>
<li class="toctree-something">other</a></li>
<li class="toctree-l1">examples</a></li>
<li class="toctree-l2">charcnn</a></li>
<li class="toctree-l3">cifar10</a></li>
Если у вас есть параметры для замены в словаре ( dict
), вы могли бы написать некоторый код, который генерирует sed
команды из вашего словаря в форме
s#(<li class="toctree-)[^"]*(">
key
</a></li>)#1
value
2#
В зависимости от ваших потребностей вы можете использовать разные или более короткие шаблоны, такие как
s#("toctree-)[^"]*(">examples<)#1l12#
Редактировать после уточнения вопроса в комментарии:
Чтобы изменить исходный файл, вы можете либо сохранить sed
выходные данные в новом файле, а в случае успеха переименовать его в исходное имя файла, например
sed -e 'sed-command' inputfile > outputfile amp;amp; mv outputfile inputfile
или используйте -i
опцию (редактирование на месте), если она доступна
sed -i -e 'sed-command' inputfile
(Обратите внимание, что вы можете потерять исходный ввод, если ваша команда содержит ошибку.)
Ответ №2:
awk -v dict="{'example':l1, 'charcnn':l2, 'cifar10':l3}" '
BEGIN{
dict1=gensub(/[}{'"'"' ]/,"","g",dict);
split(dict1,map,",") }
/toctree/ {
cnt ;
split(map[cnt],map1,":");
print "<li class="toctree-"map1[2]"">"map1[1]"</a></li>" }
' htmlfile
Одна строка:
awk -v dict="{'example':l1, 'charcnn':l2, 'cifar10':l3}" 'BEGIN{ dict1=gensub(/[}{'"'"' ]/,"","g",dict);split(dict1,map,",") } /toctree/ {cnt ;split(map[cnt],map1,":");print "<li class="toctree-"map1[2]"">"map1[1]"</a></li>" }' htmlfile
Предполагая, что «toctree» больше нигде не существует в htmlфайле, вы можете попробовать выше. Сначала передайте dict в качестве переменной в awk, а затем в блоке begin удалите ненужные символы и используйте функцию split для размещения записей в массиве с именем map . Затем мы ищем любые строки с toctree, увеличиваем счетчик cnt, разделяем запись массива map на map1, используя «:» в качестве разделителя, и печатаем отформатированные строки по мере необходимости.
Печать, несомненно, потребует работы, чтобы обеспечить правильный отступ.
Комментарии:
1. Я предлагаю объяснить ваш
awk
код. Насколько я понимаю, он не будет проверять ключевыеexample
слова,charcnn
… но обрабатывает словарь по порядку независимо от количества и порядка совпадающих входных строк.2. Да, это то, что я понял как требование. Порядок списка будет зависеть от порядка записей в dict
3. Я предлагаю объяснить это в вашем ответе. Вопрос не совсем ясен в отношении требований. Из названия
dict
я предположил, что оно подразумевается как словарь, который не обязательно имеет определенный порядок.