Как использовать sed для поиска и замены строк кода HTML из входных переменных awk - PullRequest
1 голос
/ 19 сентября 2019

У меня есть 6 текстовых файлов с 10 столбцами и 19 строками.Первая строка каждого текстового файла содержит идентичный заголовок (намеренно игнорируется awk).Я создаю заголовок как часть заголовка таблицы для форматирования.

Пример - foo1.txt (сокращен до первых 4 строк подготовленных данных):

H1 H2 H3 H4 H5 H6 H7 H8 H9 H10
1 2 3 4 5 6 7 8 9 10
2 3 4 5 6 7 8 9 10 11
3 4 5 6 7 8 9 10 11 12

Шаблон htmlфайл, содержащий некоторые CSS, позиции таблиц и строки таблиц для замены.Важно, чтобы этот html-файл шаблона не перезаписывался, так как он должен использоваться много раз для других случаев (другие наборы из 6 текстовых файлов).Строки таблицы (MYTABLE1, MYTABLE2,…) будут тем, что должно быть заменено сценарием оболочки.

Пример - template.html:

    <!--some html and css code, followed by below code-->
    <div>
    <div class="wrap">
    <table>
    <caption>foo1</caption>
    <tbody>
    MYTABLE1
    </tbody>
    </table>
    </div>
    <div>
    <div class="wrap">
    <table>
    <caption>foo2</caption>
    <tbody>
    MYTABLE2
    </tbody>
    </table>
    </div>
    <div>
    <div class="wrap">
    <table>
    <caption>foo3</caption>
    <tbody>
    MYTABLE3
    </tbody>
    </table>
    </div>
    <!--then, continues through foo6 and MYTABLE6 and other html code-->

Сценарий bash открывает каждый текстовый файли, используя awk, создает строку и читает из файлов, чтобы заполнить каждую строку ниже строки заголовка.Таблица html включена между значениями, поступающими из текстовых файлов.Выходные данные awk хранятся в виде переменной, которая затем передается в sed для поиска в файле template.html строк MYTABLE * и замены их переменными, содержащими дополнительный код таблицы.Затем sed должен создать новый HTML-файл, чтобы не записывать поверх файла template.html.Часть скрипта на awk работает как задумано, однако часть sed жалуется на 's /' и терпит неудачу.Я предполагаю, что это потому, что передается HTML-код?Я пробовал несколько способов заставить sed принять строковую переменную, при этом каждая попытка имела символ 's / fail.

Пример - make_table.sh (включены только первые 3 элемента таблицы для создания):

#!/bin/bash

STRING1=$(cat foo/foo1.txt | awk ' NR==1{next} BEGIN {
print "<tr><th class=\x22right\x22>H1</th>", "<th class=\x22right\x22>H2</th>", "<th>H3</th>", "<th>H4</th>", "<th>H5</th>", "<th>H6</th>", "<th>H7</th>", "<th>H8</th>",  "<th>H9</th>", "<th>H10</th></tr>" }
{ print "<tr><td class=\x22right\x22>" $1 "</td><td class=\x22right\x22>" $2 "</td><td>" $3 "</td><td>" $4 "</td><td>" $5 "</td><td>" $6 "</td><td>" $7 "</td><td>" $8 "</td><td>" $9 "</td><td>" $10 "</td></tr>" }')

STRING2=$(cat foo/foo2.txt | awk ' NR==1{next} BEGIN {
print "<tr><th class=\x22right\x22>H1</th>", "<th class=\x22right\x22>H2</th>", "<th>H3</th>", "<th>H4</th>", "<th>H5</th>", "<th>H6</th>", "<th>H7</th>", "<th>H8</th>",  "<th>H9</th>", "<th>H10</th></tr>" }
{ print "<tr><td class=\x22right\x22>" $1 "</td><td class=\x22right\x22>" $2 "</td><td>" $3 "</td><td>" $4 "</td><td>" $5 "</td><td>" $6 "</td><td>" $7 "</td><td>" $8 "</td><td>" $9 "</td><td>" $10 "</td></tr>" }')

STRING3=$(cat foo/foo3.txt | awk ' NR==1{next} BEGIN {
print "<tr><th class=\x22right\x22>H1</th>", "<th class=\x22right\x22>H2</th>", "<th>H3</th>", "<th>H4</th>", "<th>H5</th>", "<th>H6</th>", "<th>H7</th>", "<th>H8</th>",  "<th>H9</th>", "<th>H10</th></tr>" }
{ print "<tr><td class=\x22right\x22>" $1 "</td><td class=\x22right\x22>" $2 "</td><td>" $3 "</td><td>" $4 "</td><td>" $5 "</td><td>" $6 "</td><td>" $7 "</td><td>" $8 "</td><td>" $9 "</td><td>" $10 "</td></tr>" }')

echo $STRING1
#everything above works as intended

#I've tried (with no luck):
#sed -e 's/MYTABLE1/'${STRING1}'/' \
#sed -e 'c/MYTABLE1/'"$(echo ${STRING1})"'/' \

#below does not work
sed -e 's/MYTABLE1/'"$(echo ${STRING1})"'/' \
    -e 's/MYTABLE2/'"$(echo ${STRING2})"'/' \
    -e 's/MYTABLE3/'"$(echo ${STRING3})"'/' \
    < template.html > template_new.html

Как мне заставить sed принимать эти команды STRING *?Может ли это быть сделано в чистом awk (не уверен, что awk может прочитать template.html и записать вывод в template_new.html).Я действительно хотел бы избежать чистого решения sed, поскольку помимо простой подстановки строк формат sed не имеет смысла.Могу ли я лучше оптимизировать код awk?

Ответы [ 3 ]

2 голосов
/ 19 сентября 2019

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

sed -e "s#MYTABLE1#${STRING1}#"  \
    -e "s#MYTABLE2#${STRING2}#"  \
    -e "s#MYTABLE3#${STRING3}#"  \
    < template.html > template_new.html

Примечание. Я также сократил цитирование и удалил ненужные команды echo.

В соответствии со спецификацией POSIX вы можетеиспользуйте любой символ в качестве разделителя для команды s, кроме обратной косой черты или новой строки.Хотя GNU sed даже примет обратную косую черту.Смотрите: Какие разделители вы можете использовать в sed?

0 голосов
/ 19 сентября 2019

Решение состоит в том, чтобы использовать то, что у меня было, и только изменить разделитель на что-то отличное от косой черты.Следующие работы:

sed -e 's#MYTABLE1#'"$(echo ${STRING1}"'#'  \
    -e 's#MYTABLE2#'"$(echo ${STRING2}"'#'  \
    -e 's#MYTABLE3#'"$(echo ${STRING3}"'#'  \
    < template.html > template_new.html
0 голосов
/ 19 сентября 2019

Если вы знаете имена файлов файлов данных во время создания шаблона, что в вашем примере выглядит так, как вы, вы можете выполнить всю эту работу с одним процессом awk (и безопасно),Предположим, что шаблон содержит строки типа MYTABLE foo1.txt, которые должны быть заменены всем остальным, оставленным без изменений, и использование некоторых переменных, чтобы сделать код короче и понятнее:

awk <template >new '
BEGIN{ a="<tr>"; b="<th class=\x22right\x22>"; c="<th>"; d="</th>"; e="</tr>";
  h=a b "H1" d b "H2" d c "H3" d c "H4" d c "H5" d c "H6" d c "H7" d c "H8" d c "H9" d c "H10" d e;
  b="<td class=\x22right\x22>"; c="<td>"; d="</td>" }
$1=="MYTABLE" { f=$2; getline <f; print h; 
  while((getline <f)>0){ print a b $1 d b $2 d c $3 d c $4 d c $4 d c $4 d c $5 d c $6 d c $7 d c $8 d c $9 d c $10 d e };
  close(f); next }
{ print }'

# the close(f) is only required if you have too many files for awk to open concurrently,
# but good practice always

Также обратите внимание, что можно поставить скрипт awkв файле с -f вместо командной строки, но функциональность одинакова в любом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...