关于bash:你可以着色从文件中抓取的特定行吗?

Can you colorize specific lines that are grepped from a file?

我每周运行一个crontab,它从40多个远程服务器收集硬件信息,并在我们的家庭办公室的报表服务器上创建每周日志文件。我有一个脚本,我对这个每周文件运行,只输出特定的状态行到我的显示器。

1
2
3
4
5
6
7
8
9
#!/bin/sh

# store newest filename to variable
DD_FILE="$(ls -t /home/user/ddinfo/|head -1)"

# List the site name, disk ID (virtual & physical), Status and State of each ID, Failure Prediction for each physical disk, and the site divider
grep -w 'Site\|^ID\|^State\|^Status\|^Failure Predicted\|^##' /home/user/ddinfo/$DD_FILE
echo"/home/user/ddinfo/"$DD_FILE
exit 0

这是一个示例输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Accessing Site: site01
ID                            : 0
Status                        : Ok
State                         : Ready
ID                              : 0:0:0
Status                          : Ok
State                           : Online
Failure Predicted               : No
ID                              : 0:0:1
Status                          : Ok
State                           : Online
Failure Predicted               : No
################################################
Accessing Site: site02
ID                            : 0
Status                        : Ok
State                         : Ready
ID                              : 0:0:0
Status                          : Non-Critical
State                           : Online
Failure Predicted               : Yes
ID                              : 0:0:1
Status                          : Ok
State                           : Online
Failure Predicted               : No
################################################

有没有一种方法来cat/grep/sed/awk/perl/这个输出,使以CriticalYes结尾的任何行都着色?


使用GNU GREP:

1
grep --color -E".*Yes$|.*Critical$|$" file


你可以试试ACK,一个很好的grep替代品:

1
2
3
% ack '(Critical|Yes)$' file
# Or to colorize the whole line:
% ack '(.*(Critical|Yes))$' file

超越grep

或者,如果要查看所有行,并且只给特定行上色:

1
2
3
4
5
use Term::ANSIColor qw/ colored /;
while (<$fh>) {
    s/(.*)(Critical|Yes)$/colored(["yellow bold"], $1.$2)/e;
    print;
}


要查看除CriticalYes上色以外的所有行,请尝试:

1
awk -v on="$(tput smso)" -v off="$(tput rmso)" '/(Critical|Yes)$/{$0=on $0 off} 1' logfile

它使用tput创建适合您的终端的代码。出于演示目的,我选择了smso/rmso来设置和重置"突出模式"。您可以使用tput支持的任何其他功能。

变化

如果我们希望文本为红色而不是"突出模式":

1
awk -v on="$(tput setaf 1)" -v off="$(tput sgr0)" '/(Critical|Yes)$/{$0=on $0 off} 1' logfile

tput setaf 1是创建红色的代码。(在tput中,红色为1,绿色为2等)。tput sgr0是关闭所有属性的代码。

工作原理

  • 埃多克斯1〔10〕

    这定义了两个awk变量,onoff,它们可以打开和关闭我们喜欢的任何颜色效果。

  • 埃多克斯1〔13〕

    对于以CriticalYes结尾的任何行,我们将on代码添加到行的前面,并将off代码添加到行的末尾。

  • 埃多克斯1〔18〕

    这是awk用来打印行的神秘速记。


您可以使用Perl的Term::ANSIColor模块:

1
... | perl -pne 'BEGIN { use Term::ANSIColor } /: (Yes|Critical)$/ && { $_ = color("red") ."$_" . color("reset") }'


感谢您的所有回复。最后我把原来的grep结果通过管道传输到另一个grep | grep --color=auto '.*\(Yes\|Critical\).*\|$'上,得到了我想要的彩色结果:

1
grep -i 'site\|^ID\|^State\|^Status\|^Failure Predicted\|^##' /home/user/ddinfo/$DD_FILE | grep --color=auto '.*\(Yes\|Critical\).*\|$'

这是新的样本输出:

Sample Output