通过 awk 或其他方法搜索行并为其着色

通过 awk 或其他方法搜索行并为其着色

我尝试过用其他方法创建 awk 脚本或脚本。

我希望日志文件中包含日期和时间变量(但包含给定单词)的给定行用特定颜色加下划线。

我在 awk 中创建了类似的东西,但它只强调某个短语,没有日期和时间,是否可以另外强调日期和时间或包含该单词的整行?

awk $'{ gsub(" DEBUG StateMachine\|entr \'NTP:nextGetTimeTimeoutState'", "\033[1;41m&\033[0m");
print }' LOG.log

LOG.log 中的这一行看起来像这样:

2021-08-17 10:16:35,445 DEBUG StateMachine|exit 'NTP:nextGetTimeTimeoutState'
2021-08-17 10:16:35,445 DEBUG StateMachine|entr 'NTP:nextIteratorState'
2021-08-17 10:16:35,445 INFO StateMachine|task 'NTP:nextIteratorState'
2021-08-17 10:16:35,449 DEBUG StateMachine|exit 'NTP:nextIteratorState'
2021-08-17 10:16:35,449 DEBUG StateMachine|entr 'NTP:nextGetTimeTimeoutState'
2021-08-17 10:16:35,449 INFO StateMachine|wait 60000 NTP:nextGetTimeTimeoutState

答案1

每当您发现自己使用$'{...}'awk 脚本时,您就做错了什么,应该寻求帮助。切勿这样做,因为在编写良好的脚本中从来不需要这样做,并且会导致脚本变得脆弱,因为它会在 awk 看到它之前邀请 shell 解释它的某些部分。

有些人在遇到问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。:-)

您正在转义正则表达式元字符以使正则表达式表现得像字符串一样。不要这样做 - 当您想要匹配字符串时,只需使用字符串而不是正则表达式运算符:

awk 'index($0,"DEBUG StateMachine|entr \047NTP:nextGetTimeTimeoutState\047") {
    $0 = "\033[1;41m" $0 "\033[0m"
}
1' LOG.log

使用 s\047而不是's 是因为您无法''shell 中转义 - 分隔字符串(包括脚本)中的 a 。看http://awk.freeshell.org/PrintASingleQuote

要使用相同颜色突出显示 2 条不同的线,您可以使用:

awk '
    index($0,"DEBUG StateMachine|entr \047NTP:nextGetTimeTimeoutState\047") ||
    index($0,"DEBUG StateMachine|exit \047NTP:nextGetTimeTimeoutState\047") {
        $0 = "\033[1;41m" $0 "\033[0m"
    }
1' LOG.log

并用 2 种不同颜色突出显示 2 条线:

awk '
    index($0,"DEBUG StateMachine|entr \047NTP:nextGetTimeTimeoutState\047") {
        $0 = "\033[1;42m" $0 "\033[0m"
    }
    index($0,"DEBUG StateMachine|exit \047NTP:nextGetTimeTimeoutState\047") {
        $0 = "\033[1;41m" $0 "\033[0m"
    }
1' LOG.log

话虽如此,由于您显然正在尝试根据输入的不同部分使用不同的颜色,因此现在最好使用带有捕获组的正则表达式来隔离输入的相关部分,然后只需查看这些部分即可确定每行使用的颜色,以下是我如何使用 GNU awk 作为第三个参数来实现捕获组的 match() :

$ cat tst.awk
BEGIN {
    red    = "\033[1;41m"
    green  = "\033[1;42m"
    yellow = "\033[1;43m"
    blue   = "\033[1;44m"
    purple = "\033[1;45m"
    reset  = "\033[0m"

    map["nextGetTimeTimeoutState","entr"] = green
    map["nextGetTimeTimeoutState","exit"] = red
    map["nextIteratorState","entr"]       = yellow
    map["nextIteratorState","task"]       = blue
    map["nextIteratorState","exit"]       = purple
}
match($0,/(DEBUG|INFO) StateMachine\|(\S+)\s+\047NTP:([^\047]+)\047/,a) {
    key = a[3] SUBSEP a[2]
    if ( key in map ) {
        $0 = map[key] $0 reset
    }
}
{ print }

或使用任何 POSIX awk:

$ cat tst.awk
BEGIN {
    red    = "\033[1;41m"
    green  = "\033[1;42m"
    yellow = "\033[1;43m"
    blue   = "\033[1;44m"
    purple = "\033[1;45m"
    reset  = "\033[0m"

    map["nextGetTimeTimeoutState","entr"] = green
    map["nextGetTimeTimeoutState","exit"] = red
    map["nextIteratorState","entr"]       = yellow
    map["nextIteratorState","task"]       = blue
    map["nextIteratorState","exit"]       = purple
}
match($0,/(DEBUG|INFO) StateMachine\|[^[:space:]]+[[:space:]]+\047NTP:[^\047]+\047/) {
    split($0,a,/[|[:space:]:\047]+/)
    key = a[9] SUBSEP a[7]
    if ( key in map ) {
        $0 = map[key] $0 reset
    }
}
{ print }

无论您使用哪一种,输出都将是:

在此输入图像描述

你不需要中间变量redgreen等,就像你可以做的那样:

    map["nextGetTimeTimeoutState"]["entr"] = "\033[1;42m"
    map["nextGetTimeTimeoutState"]["exit"] = "\033[1;41m"

但我发现拥有它们有助于清晰和轻松地进行未来的维护/更新。

答案2

如果我理解正确,你可以使用正则表达式和单引号的八进制表示(\047)像这样:

awk '{ sub(/^.*DEBUG StateMachine\|entr \047NTP:nextGetTimeTimeoutState\047/, "\033[1;41m&\033[0m/); print }' LOG.log

在此输入图像描述

答案3

由于这是一个简单的“对多个匹配行进行编辑”,因此您不需要 awk 的强大功能。正如其他人所指出的,您的大部分问题在于正确引用。

使用 sed,一行

sed "/DEBUG StateMachine|entr 'NTP:nextGetTimeTimeoutState'/s/.*/"$'\e[[1;41m&\e[0m'/

或在 3

PAT=" DEBUG StateMachine|entr 'NTP:nextGetTimeTimeoutState'"
TO=$'\e[[1;41m&\e[0m'
sed "/$PAT/s/.*/$TO/"

答案4

至于其他方法,存在类似colorize或这样的包ccze

您可以在其中输入一些文本,它们会美化您的输出。大多数使用通用颜色配置文件,但也可以编写自己的颜色配置文件。

首先尝试使用默认值,看看您是否喜欢它。

相关内容