Bash
通過 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
任何時候你發現自己
$'{...}'
在使用 awk 腳本時都做錯了,應該尋求幫助。永遠不要這樣做,因為在編寫良好的腳本中從來不需要這樣做,並且會導致您的腳本變得脆弱,因為它邀請 shell 在 awk 甚至看到它之前解釋它的某些部分。有些人在遇到問題時會想“我知道,我會使用正則表達式”。現在他們有兩個問題。:-)
您正在轉義正則表達式元字元以使您的正則表達式表現得像一個字元串。不要那樣做——當你想匹配一個字元串時,只需使用字元串而不是正則表達式運算符:
awk 'index($0,"DEBUG StateMachine|entr \047NTP:nextGetTimeTimeoutState\047") { $0 = "\033[1;41m" $0 "\033[0m" } 1' LOG.log
\047
s 而不是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 作為第三個 arg to 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 }
無論您使用哪個輸出都將是:
您不需要中間變數
red
,green
等,因為您可以這樣做:map["nextGetTimeTimeoutState"]["entr"] = "\033[1;42m" map["nextGetTimeTimeoutState"]["exit"] = "\033[1;41m"
但我發現擁有它們有助於清晰和便於未來的維護/更新。