我有以下名为 test.html 的文件:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<meta name="generator" content="SQL*Plus 12.2.0">
<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;-
} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title>
</head>
<body>
<p>
<table border='1' width='90%' align='center' summary='Script output'>
<tr>
<th scope="col">
NAME
</th>
<th scope="col">
FREE_PERCENT
</th>
</tr>
<tr>
<td>
DG_BACKUP
</td>
<td>
50%
</td>
</tr>
<tr>
<td>
DG_DATA
</td>
<td>
96%
</td>
</tr>
<tr>
<td>
DG_INDEX
</td>
<td>
80%
</td>
</tr>
<tr>
<td>
DG_ORA
</td>
<td>
19%
</td>
</tr>
</table>
<p>
<br>
</body>
</html>
我想找到小于 20% 的值并将背景设置为红色:
<td bgcolor="red">
使用 sed 或任何其他工具。所以,举例来说,
<td>
80%
</td>
将保持不变,但是
<td>
19%
</td>
伤口改为
<td bgcolor="red">
19%
</td>
到目前为止我已经尝试过的脚本。
number_of_lines_test=(`grep -n % test.html |sed -e '1d' |awk -F"[:%]" '{if ($2 <= 50) print $1}'`)
for i in `seq 0 $((${#number_of_lines_test[@]} - 1))`
do
sed -i -e "$((${number_of_lines_test[i]} - 1))s/<td>/<td bgcolor=\"red\">/" test.html
done
答案1
我认为您了解您的解决方案,并且西瓦普拉萨的回答,运行sed
一次对于每条需要更改的数据线
(除了运行grep
和awk
一次,以及在代码中额外的sed
)。
awk
并且sed
是非常强大的命令。您几乎不会将它们一起使用,或者与 一起使用grep
。awk
知道行号。如果您发现自己使用grep -n
生成行号,然后使用 处理它们awk
,那么您可能为自己做了比您需要的更多的工作。- 运行命令需要时间。如果您的文件有 100 行长,您可能不会注意到 SivaPrasath 的回答所花费的时间。如果您的文件有一百万行长,SivaPrasath 的答案将运行
sed
大约 125,000 次。这可能会很明显,但没有必要。
如果“值”始终为 的形式,其中NN%
NN
00
是和 之间的两位十进制整数 19
,您可以使用此sed
命令执行所有操作:
sed '/<td>/ { N; s/\(<td\)\(>\n[01][0-9]%\)/\1 bgcolor="red"\2/; }' test.html
当它看到包含 的行时,它会执行...大括号<td>
中的命令。 从文件中读取下一行(包含该值的行)并将其附加到模式空间。然后 ,如果(百分比)值匹配(即通过 ),它会执行(替代)替换。{
}
N
s
<td>
<td bgcolor="red">
[01][0-9]
00
19
如果该值可以是单个数字(即0
through9
而不是00
through 09
),则使用
sed '/<td>/ { N; s/\(<td\)\(>\n[0-9]%\)/\1 bgcolor="red"\2/; s/\(<td\)\(>\n[01][0-9]%\)/\1 bgcolor="red"\2/; }'
这是相同的逻辑,但用一个s
命令来处理单位数值,用一个命令来处理两位数值。或者,如果您有 GNU sed
(Linux 系统上的标准),您可以这样做
sed -r '/<td>/ { N; s/(<td)(>\n[01]?[0-9]%)/\1 bgcolor="red"\2/; }' test.html
它使用扩展正则表达式[01]?[0-9]
来匹配任何一个一位数或小于 20 的两位数。
sed
可以处理非整数(例如17.5%
)、两位以上数字(带前导零)的值和负数。如果你编辑你的问题为了表明您需要处理哪些表格,我将更新此部分。
awk
程序虽然有点冗长,但功能更强大,因为它们可以轻松地记住从一行到另一行的信息。因此,下面的脚本可以识别多种数字形式:
awk -F% '
last_was_td {
if ($1 < 20) print "<td bgcolor=\"red\">"
else print "<td>"
}
{ last_was_td = 0 }
/<td>/ {
last_was_td = 1
next
}
{ print }
' test.html
从中间开始阅读。如果一行包含<td>
,则程序设置last_was_td
标志并跳到下一个输入行。否则该标志将被清除并打印该行。现在从顶部读取脚本:如果上一行是 a <td>
,并且数字(第一个字段,由%
字段分隔符分隔)小于 20,我们打印<td bgcolor="red">
;否则我们打印<td>
. (该值本身由print
最后的一般语句打印。)
上述所有答案都将修改后的文件写入标准输出。如您所知,您可以使用sed -i
.使用awk
,将输出写入临时文件并将其复制回输入文件。
答案2
尝试这个,
number=(`grep -n "^[0-1][0-9]" test.html | awk -F ':' '{a=$1-1;print a}'`)
for i in ${number[@]}
do
sed -i "$i s/.*/<td bgcolor=\"red\">/" test.html
done
答案3
使用乐(以前称为 Perl_6)
raku -e 'put S:g/^^ (\< td) \> $$ \n ^^ (<digit>**2) \% $$ /{$1 < 20 ?? "$0 bgcolor=\"red\">\n$1" !! "$0>\n$1"}/ given lines.join("\n");'
#OR
raku -e 'put S:g[^^ (\< td) \> $$ \n ^^ (<digit>**2) \% $$] = $1 < 20 ?? "$0 bgcolor=\"red\">\n$1" !! "$0>\n$1" given lines.join("\n");'
或者
raku -e 'put S:g/^^ (\< td) \> $$ \n ^^ (<digit>**2) \% $$ /{$1 < 20 ?? "$0 style=\"background-color:#ff0000;\">\n$1" !! "$0>\n$1"}/ given lines.join("\n");'
#OR
raku -e 'put S:g[^^ (\< td) \> $$ \n ^^ (<digit>**2) \% $$] = $1 < 20 ?? "$0 style=\"background-color:#ff0000;\">\n$1" !! "$0>\n$1" given lines.join("\n");'
示例 1 和 2 替换为bgcolor="red"
.示例 3 和 4 替换 -in style="background-color:#ff0000;"
,以生成可在现代浏览器上运行的 html。
简而言之,这些示例使用 Raku 的“大S”替换运算符,(根据文档),“保留原始字符串完整并返回结果字符串而不是 $/ (匹配变量)”。
乐的“大S”在上面的所有 4 个示例中,运算符与 Raku 的三元运算符一起使用。 Raku 的三元运算符拼写为:“'Condition' ??
'True' !!
'False'”。
示例 1 和 3 使用传统S/old/new/
格式,在 Raku 中可以在右半部分采用代码块。示例 2 和 4 使用更现代的S[old] = "new"
或S[old] = [new]
替换运算符格式,它(如演示的)可以采用三元运算符和/或条件语句(本质上是不带花括号的代码块)。
https://docs.raku.org/syntax/S$SOLIDUS$SOLIDUS$SOLIDUS
https://docs.raku.org/language/operators#index-entry-operator_ternary
https://raku.org