请帮我优化一下bash脚本。执行时间太长
要求:我正在使用的日志文件在行开头有一些带日期的行,而有些行在行开头没有日期。
我需要从上行插入日期,如果日期不在行开始。
我在Windows 10下的MingW64工作。
日期格式:2022-06-09 17:47:08,371
给定文件:
date1 string1
string2 date(只是日志中的日期,而不是行开头的日期)
, string3
date2 string4
string5
]string6
date3 string7
date4 string8
date5 string9
文件示例:
2022-06-09 10:00:01,000 string1
string2 2022-06-09 10:00:01,000 string2 2022 string2
, string3 string3 string3
2022-06-09 10:00:02,000 string4
string5
]string6 string6 string6
}
2022-06-09 10:00:03,000 string7 string7
2022-06-09 10:00:04,000 string8 string8
2022-06-09 10:00:05,000 string9
预期文件:
date1 string1
date1 string2 date
date1, string3
date2 string4
date2 string5
date2]string6
date3 string7
date4 string8
date5 string9
文件示例:
2022-06-09 10:00:01,000 string1
2022-06-09 10:00:01,000 string2 2022-06-09 10:00:01,000 string2 2022 string2
2022-06-09 10:00:01,000 , string3 string3 string3
2022-06-09 10:00:02,000 string4
2022-06-09 10:00:02,000 string5
2022-06-09 10:00:02,000 ]string6 string6 string6
2022-06-09 10:00:02,000 }
2022-06-09 10:00:03,000 string7 string7
2022-06-09 10:00:04,000 string8 string8
2022-06-09 10:00:05,000 string9
需要优化的脚本
我试了如下:
我用loop来做,它很慢
nn_lines_to_replace=$(grep -Evn "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}" "$file" | cut -d ":" -f1)
for nn_line in $nn_lines_to_replace ; do
replace=$(sed -n $(($nn_line-1))p "$file"|cut -d " " -f1-2)
sed -i ""$nn_line" s/^/$replace/" "$file"
done
也许可以用sedawk或.
如果你有想法如何优化它或有更好的方法,请分享,我将非常感谢任何帮助
更新:我把这个问题复杂化了link
我在评论中给出了下一个解决方案,该解决方案适用于OP:
您的解决方案应该在文件中循环一次。对于每一行检查一个日期,当它是一个日期时把它放在一个变量中,或者用var写最后一个日期。
awk '
/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}/ {last_d_t=$1 " " $2; print; next}
{print last_d_t $0}
' inputfile
我将按照以下方式利用GNUAWK
来完成这项任务,让file.txt
内容为
2022-06-09 10:00:01,000 string1
string2 2022-06-09 10:00:01,000 string2 2022 string2
, string3 string3 string3
2022-06-09 10:00:02,000 string4
string5
]string6 string6 string6
}
2022-06-09 10:00:03,000 string7 string7
2022-06-09 10:00:04,000 string8 string8
2022-06-09 10:00:05,000 string9
然后
awk '/^20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]/{d=substr($0, 1, 24);print;next}{print d $0}' file.txt
输出2022-06-09 10:00:01,000 string1
2022-06-09 10:00:01,000 string2 2022-06-09 10:00:01,000 string2 2022 string2
2022-06-09 10:00:01,000 , string3 string3 string3
2022-06-09 10:00:02,000 string4
2022-06-09 10:00:02,000 string5
2022-06-09 10:00:02,000 ]string6 string6 string6
2022-06-09 10:00:02,000 }
2022-06-09 10:00:03,000 string7 string7
2022-06-09 10:00:04,000 string8 string8
2022-06-09 10:00:05,000 string9
解释:对于以20
开头的行,后面跟着2位数字,后面跟着-
,后面跟着2位数字,后面跟着-
,后面跟着2位数字,我使用substr
函数提取24个第一个字符,并将其存储在变量d,print
行中,并指示GNUAWK
转到next
行,因此第二个动作应用于所有不匹配所述正则表达式的行-对于它们,我将它们打印出来,前面加上变量d的值。免责声明:此解决方案假设您正在处理2000年的日期…2099的范围,并且任何以描述的正则表达式开头的行都包含固定宽度的日期时间字符串,并且对于每个没有日期时间字符串的行,都存在日期时间更早的行。
(在gawk 4.2.1中测试)
它有一个partialregex
检查datetime
-
。高级数字+ sep格式,
——而不是每个数字验证
{m,g}awk ' BEGIN { 1 _="-- ::," (__="[09]") 1 gsub("[[, :-]",(__)(__) "&",_) 1 sub("^", (__) (__), _) 1 gsub( !_, &-", _) 1 ___=length(FS="^"(_)" ")*(_^=__="") } $! NF = sprintf("%.*s%s%.*s", (_!=(NF-_) * ___, __, $!_,+_<+_, _ ~ NF ?"":__=substr($!_,_,___))'
|
2022-06-09 10:00:01,000 string1
2022-06-09 10:00:01,000 string1string2 2022-06-09 10:00:01,000 string2 2022 string2
2022-06-09 10:00:01,000 string1, string3 string3 string3
2022-06-09 10:00:02,000 string4
2022-06-09 10:00:02,000 string4string5
2022-06-09 10:00:02,000 string4]string6 string6 string6
2022-06-09 10:00:02,000 string4}
2022-06-09 10:00:03,000 string7 string7
2022-06-09 10:00:04,000 string8 string8
2022-06-09 10:00:05,000 string9
字符串奇怪地聚集在一起。哦,好吧,这就是生活