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

Bla*_*ler 3 bash logs awk shell-script

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

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

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

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

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
Run Code Online (Sandbox Code Playgroud)

Ed *_*ton 10

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

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

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

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

使用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
Run Code Online (Sandbox Code Playgroud)

并用 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
Run Code Online (Sandbox Code Playgroud)

话虽如此,由于您显然正在尝试根据输入的不同部分使用不同的颜色,因此现在最好使用带有捕获组的正则表达式来隔离输入的相关部分,然后只需查看这些部分即可确定每行使用的颜色,以下是我如何使用 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 }
Run Code Online (Sandbox Code Playgroud)

或使用任何 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 }
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

您不需要中间变量,等等,因为您可以这样做redgreen

    map["nextGetTimeTimeoutState"]["entr"] = "\033[1;42m"
    map["nextGetTimeTimeoutState"]["exit"] = "\033[1;41m"
Run Code Online (Sandbox Code Playgroud)

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