我需要在匹配的模式之后获取下一行,并且需要从该行剪切或裁剪两个模式之间的值。
示例源文件
<h2>Commodity Information</h2>
<dl>
<dt>Commodity Orgin</dt>
<dd>uerb45e001.material.com</dd>
<dt>Commodity Code & Dimension</dt>
<dd>151151.15 Dim 90 </dd>
<dt>Commodity Serial #</dt>
<dd>2009081020</dd>
<dt>Client Name</dt>
<dd>Jack</dd>
</dl>
期望的输出:
Commodity Orgin : uerb45e001.material.com
Commodity Code & Dimension : 151151.15 Dim 90
Commodity Serial # : 2009081020
Client Name : Jack
答案1
lynx -dump
将 HTML 转换为纯文本,然后awk
重新格式化输出,将字段分隔符设置为换行符 ( \n
),将记录分隔符设置为两个或更多换行符 ( \n\n+
)。
sub()
脚本中的函数调用会在awk
打印所需的输出之前删除多余的空格。
$ lynx -dump ramp.html |
awk -v RS='\n\n' -F'\n' '/^[[:space:]]+/ {
sub(/^ +/,"",$1);
sub(/ +/," ",$2);
print $1":"$2
}'
Commodity Orgin: uerb45e001.material.com
Commodity Code & Dimension: 151151.15 Dim 90
Commodity Serial #: 2009081020
Client Name: Jack
我真的不喜欢这样做,因为解析 XML 或 HTML 从来都不是一个好主意用正则表达式。它不起作用。即使你可以将其破解,使其看起来可以正常工作,但它也非常脆弱并且将要一旦 HTML 或 XML 与您的正则表达式所寻找的内容发生足够大的变化,就会中断。真正的 XML 或 HTML 解析器是仅有的能够正确完成工作的东西。
但是,话虽如此,这里有一些仅使用sed
和 的fmt
工具,这些工具应该在任何类 UNIX 系统上可用:
$ sed -e '/<d[td]\|^[[:blank:]]*$/!d
s/<[^>]*>//g;
s/^ *//;
/^\(Commodity\|Client\)/ s/$/:/' ramp.html |
fmt |
sed -e '/^[[:blank:]]*$/d'
Commodity Orgin: uerb45e001.material.com
Commodity Code & Dimension: 151151.15 Dim 90
Commodity Serial #: 2009081020
Client Name: Jack
第一个sed
脚本删除所有行除了空行和包含 a<DT>
或<DD>
标记的行,然后它会从输入中删除所有 HTML 标记,删除前导空格并将 a 添加:
到字段名称行的末尾。然后将输出sed
通过管道输入fmt
以重新格式化行,然后sed
再次输入以删除空白行。
这是一个 hack,仅保证能够准确地处理您提供的示例输入。任何实质性的不同都可能会破坏脚本。这就是当您使用正则表达式来解析除最简单的 HTML 或 XML 之外的任何内容时所发生的情况。
答案2
如果您有xmlstarlet
,并且输入被(整理到)有效的 XML 中,您可以执行如下操作:
xmlstarlet sel --text -t -m //dt -v 'concat(., " : ", following::dd)' -nl input.html
答案3
paste -d: <(grep -oP '<dt>\K.*(?=<)' file.html) <(grep -oP '<dd>\K.*(?=<)' file.html) | sed 's/:/ : /'
Commodity Orgin : uerb45e001.material.com
Commodity Code & Dimension : 151151.15 Dim 90
Commodity Serial # : 2009081020
Client Name : Jack
- 两个
grep
命令来提取<dt>
和<dd>
标签之间的文本(假设它们与 OP 示例文件中给出的位于同一行) paste
逐行组合两个文件并:
作为分隔符sed
命令根据OP的预期输出将“:”分隔符替换为“:”(如果标签之间的文本也包含:字符,则此黑客将不起作用)- 看到这个回答有关使用
\K
和 的解释(?=)