#bash #sed #runtime-error
#bash #sed #время выполнения — ошибка
Вопрос:
Я пытаюсь манипулировать некоторыми «шаблонными» текстовыми файлами. Это означает, что файлы содержат некоторые «токены», которые необходимо заменить некоторыми реальными строками — либо жестко закодированными, либо читаемыми из других файлов.
У меня есть следующие 2 строки:
sed -r -e 's_<!-- cssintern -->_<style type="text/css">n<!-- cssintern -->n</style>n_' -i "$out_dir_aca/books_1by1/independent/$(basename "$aca_frag").html"
sed -e '^<!-- cssintern -->^' -e '{r '"$src_dir_frags_struct/styles1.css.frag" -e 'd}' -i "$out_dir_aca/books_1by1/independent/$(basename "$aca_frag").html"
Первый работает нормально. Проблема в том, что вторая генерирует ошибку «неизвестная команда», и у меня закончились идеи, как это исправить. Вывод отладки следующий (текст ошибки в последней строке):
for aca_frag in $out_dir_aca/frags_1by1/*
'[' -f '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag' ']'
basename '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
echo ' 09.14 - Acatistul inaltarii Sfintei Cruci.frag'
09.14 - Acatistul inaltarii Sfintei Cruci.frag
cat '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/1_txt_in/##_frags_struct_##/doctypeXHTML.frag'
basename '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
cat '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/1_txt_in/##_frags_struct_##/head.frag'
basename '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
cat '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/1_txt_in/##_frags_struct_##/foot.frag'
basename '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
basename '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
sed -r -e 's_<!-- cssintern -->_<style type="text/css">n<!-- cssintern -->n</style>n_' -i '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/books_1by1/independent/09.14 - Acatistul inaltarii Sfintei Cruci.frag.html'
basename '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/frags_1by1/09.14 - Acatistul inaltarii Sfintei Cruci.frag'
sed -re '^<!-- cssintern -->^' -re '{r /home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/1_txt_in/##_frags_struct_##/styles1.css.frag' -re 'd}' -i '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/books_1by1/independent/09.14 - Acatistul inaltarii Sfintei Cruci.frag.html'
sed: -e expression #1, char 1: unknown command: `^'
Я использовал для разделителей ^
, _
, /
, я использовал «все» способы с простыми и двойными кавычками и все остальное, что я нашел в Интернете. Ничто не меняет того факта, что ошибка остается.
В прошлом я использовал эту строку
sed.exe -i -e '/%%H/{r ../##_frags_##/out/%%H' -e 'd}' .outout.frag
в скрипте Windows cmd
и работал нормально. ( %%H
ссылается на имя файла при разборе всех файлов в папке с помощью a for
). Я на самом деле переписываю старые скрипты в Linux, как упражнение — надеюсь, для добавления простоты и дополнительных функций.
Я намерен адаптировать следующую sed
команду:
sed -e '/<TEXT1>/{r File1' -e 'd}' -i File2
для моих конкретных потребностей.
Примечание: я предоставил точные имена файлов и пути, думая, что они могут дать представление.
Примечание: Я использую Debian 10.7 на виртуальной машине.
Примечание: файл сценария начинается с #!/bin/bash -xv
. -xv
очевидно, используется только при отладке, в противном случае отсутствует.
Комментарии:
1. Что вы ожидаете от выражения
-e '^<!-- cssintern -->^'
? Я не вижу там команды sed.2. @larsks: Я не уверен, что понимаю ваш вопрос. Я пытаюсь реализовать решение, представленное здесь: unix.stackexchange.com/a/49438/383155 . В итоге я использовал
^
вместо/
, но ни один из них все равно не работает. Это<!-- cssintern -->
просто строка, «шаблон». Я пробовал использовать простоcssintern
, без каких-либо специальных символов, также без положительного результата.3.
-e '^<!-- cssintern -->^'
была бы допустимой командой sed. Вам нужно сообщить sed, что вы используете другой разделитель.4. @KamilCuk: я «оказался» там, когда отказался от попыток найти разделитель, который будет работать. Я начал с
/
, и это не удалось, поэтому перешел к другим. Возврат без других изменений будет бесполезным (я уже пытался, в результате вашего комментария). » Невозможно проанализировать xml с помощью регулярных выражений «. — это довольно глупо, конечно, это возможно. Я согласен, меня могут не рекомендовать по разным причинам, но это невозможно?! И учитывая, что я хочу заменить только очень конкретную строку другой строкой, я не вижу причин не использовать sed / regexes .5. @oguzismail: Я пробовал это, но безуспешно.
sed -e '^<!-- cssintern -->^' -e '{r /home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/1_txt_in/##_frags_struct_##/styles1.css.frag' -e d -e '}' -i '/home/vici/Dropbox/MyFiles/work/___rug/_!_workarea/2_txt_out/aca/books_1by1/independent/12.17 - Acatistul Sfantului Proroc Daniel.frag.html' sed: -e expression #1, char 21: missing command
. Командная строка:sed -e '^<!-- cssintern -->^' -e '{r '"$src_dir_frags_struct/styles1.css.frag" -e 'd' -e '}' -i "$out_dir_aca/books_1by1/independent/$(basename "$aca_frag").html"
.
Ответ №1:
Синтаксис такой (комментарий мой)::
[2addr] {editing command # No newline between '[2addr]' and '{'!
editing command
...
}
Где [2addr]
, например /filtering/
, выражения. Опция -e
выполняет (выделение мое):
Если указаны какие-либо опции -e или -f, сценарий редактирования команд изначально должен быть пустым. Команды, указанные каждой опцией -e или -f, должны быть добавлены в скрипт в указанном порядке. При каждом добавлении, если предыдущее добавление (если таковое было) было из опции a -e, перед новым добавлением должна быть вставлена <новая строка>. Результирующий скрипт должен иметь те же свойства, что и операнд скрипта, описанный в разделе «ОПЕРАНДЫ».
Когда между [2addr]
и есть символ {
новой строки, скрипт недействителен:
$ sed -e '/something/' -e '{' -e '}' /dev/null
sed: -e expression #1, char 11: missing command
$ sed '
/something/
{
}' /dev/null
sed: -e expression #1, char 13: unknown command: `
'
Установка {
with [2addr]
устраняет проблему, поскольку удаляет новую строку:
$ sed -e '/somethimg/{' -e '}' /dev/null
Поэтому поместите его в выражение фильтрации:
sed
-e '^<!-- cssintern -->^{'
# ^^ ^^ here '{' is with /expression/
# or just: -e '/<!-- cssintern -->/{'
-e 'r blabla/styles1.css.frag'
-e d
-e '}' -i 'blabla/12.17 - Acatistul Sfantului Proroc Daniel.frag.html'
Должно быть хорошо.
Комментарии:
1. Конечно, по-прежнему нет причин использовать
^
вместо/
в первом регулярном выражении.2. Кроме того, вероятно, объединить два сценария в один.