首先,我做了很多谷歌搜索并嘗試了 grep、sed 和 awk,但都無法找到解決方案。
我的目標是在日志檔案中找到 2 個模式,但前提是每個第一個模式都有匹配的第二個模式(它們之間沒有匹配的第一個模式)。之后,我將比較兩者的時間戳以計算兩者之間的時間,但這部分不是我卡住的地方。
我通過谷歌找到的幾乎每個解決方案都給我留下了開始和結束之間的所有行(我不需要),或者他們給我留下了第一個開始匹配和第一個結束匹配(中間有多個開始)
我正在使用的文本型別示例:
2022-09-10 20:17:05.552 [INFO] Starting process
2022-09-10 20:17:05.554 [INFO] junk here
2022-09-10 20:24:02.664 [INFO] junk here
2022-09-10 20:24:02.666 [INFO] Starting process
2022-09-10 20:30:57.526 [INFO] Starting process
2022-09-10 20:30:57.529 [INFO] Ending process
2022-09-10 20:37:55.122 [INFO] Starting process
2022-09-10 20:37:55.126 [INFO] Ending process
2022-09-10 20:44:50.352 [INFO] junk here
我想找到帶有“開始程序”然后是“結束程序”的行,但它們之間沒有“開始程序”(多次開始而沒有結束是失敗的嘗試,我只需要完成的那些)。該示例有多次失敗的啟動,但只有 2 次啟動完成:第 5-6 行和第 7-8 行
預期輸出:
2022-09-10 20:30:57.526 [INFO] Starting process
2022-09-10 20:30:57.529 [INFO] Ending process
2022-09-10 20:37:55.122 [INFO] Starting process
2022-09-10 20:37:55.126 [INFO] Ending process
實際上,我真正需要的唯一輸出是:
2022-09-10 20:30:57.526
2022-09-10 20:30:57.529
2022-09-10 20:37:55.122
2022-09-10 20:37:55.126
(因為我對這些行的唯一需要是獲取開始和結束時間來計算此任務完成時的平均時間)
我愿意在 Ubuntu 上使用通過 bash 提供的大多數命令列方法(這是用于帶有 WSL 的 Windows 機器),所以 sed/awk/grep 甚至可能 perl 都可以。
uj5u.com熱心網友回復:
awk
這是獲取匹配日期的解決方案:
awk -F ' \\[[^[]*] ' '
$2 == "Starting process" { d = $1 }
$2 == "Ending process" && d != "" { print d, $1 ; d = "" }
'
2022-09-10 20:30:57.526 2022-09-10 20:30:57.529
2022-09-10 20:37:55.122 2022-09-10 20:37:55.126
如果您使用的是 GNU awk,那么您甚至可以計算時間差:
awk -F ' \\[[^[]*] ' '
function date2time(d, _d) {
_d = d
gsub( /[:-]/, " ", _d )
return mktime(_d) substr(d, index(d,"."))
}
$2 == "Starting process" {
t = date2time($1)
}
$2 == "Ending process" && t != "" {
printf "%.03f\n", date2time($1) - t
t = ""
}
'
0.003
0.004
uj5u.com熱心網友回復:
你可以嘗試一個這樣的例程:
#!/bin/bash
######################################################################
# Finds the matching pair of two patterns
# Arguments:
# l_start_pattern - The first pattern
# l_end_pattern - The second pattern
# l_filename - Filename that we will run through each line of it
######################################################################
function find_matching_pair() {
local l_start_pattern="$1"
local l_end_pattern="$2"
local l_filename="$3"
local l_record
local l_start_pattern_found=false
local l_start_record=""
if [[ -z "${l_filename}" ]]; then
return
fi
while read l_record ; do
if [[ ${l_record} =~ ^.*${l_start_pattern} ]]; then
l_start_pattern_found=true
l_start_record="${l_record}"
fi
if [[ ${l_record} =~ ^.*${l_end_pattern} ]] &&
[[ ${l_start_pattern_found} == true ]]; then
echo "${l_start_record}"
echo "${l_record}"
l_start_pattern_found=false
l_start_record=""
fi
done < ${l_filename}
}
#
# Calls the routine and cut the output at the '[' delimiter,
# since you just need the timestamp
#
find_matching_pair "Starting process" "Ending process" "file.txt" | \
cut -d'[' -f 1
uj5u.com熱心網友回復:
這可能對您有用(GNU sed):
sed -nE '/ \[.*Starting.*/,/ \[.*Ending.*/{s///p}' file
匹配一個范圍,Starting
并且Ending
只列印修改的第一行和最后一行。
或者:
sed -nE '/Starting/{:a;N;/Ending/!ba;s/ \[.*\n(.*) \[.*/\n\1/p}' file
uj5u.com熱心網友回復:
使用 GNUsed
$ sed -En '/Starting process/t;{N;/Ending process/s/\[[^\n]*//gp}' input_file
2022-09-10 20:30:57.526
2022-09-10 20:30:57.529
2022-09-10 20:37:55.122
2022-09-10 20:37:55.126
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/508452.html