bash - 如何使用 sed 从 awk 输入变量中搜索和替换 html 代码字符串

标签 bash awk sed

我有 6 个文本文件,有 10 列和 19 行。每个文本文件的第一行包含相同的 header (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、...)将需要由 shell 脚本替换。

示例 - 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 接受字符串变量,但每次尝试都会失败。

示例 - 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 代码吗?

最佳答案

这是因为您的字符串包含 /终止 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甚至也会接受反斜杠。请参阅:What delimiters can you use in sed?

关于bash - 如何使用 sed 从 awk 输入变量中搜索和替换 html 代码字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58000857/

相关文章:

linux - 使用 Grep 或 AWK 命令

regex - awk/sed/grep/perl 使用字段分隔符然后仅显示特定行

linux - 如何使用 shell 脚本使用来自标准输入(键盘)的信息更新文件?

bash - 在 Bash 中提取单词后的字符串文本

bash - 文件中的列字符串版本,bash sed awk

bash - 如何在gradle构建脚本中添加bash和shell脚本目录路径?

html - 如何在 C 中打印前斜杠?

bash - 搜索文件 (grep/awk) 中的 2 个回车/换行字符

linux - 管道值以退出代码

linux - 如何在 Linux 中搜索两个不同日期的日志文件