如何使用 bash 更改日志文件中的日期格式,避免 while 循环

how to change date-format in a log file using bash, avoiding while loop

这不是一个新问题 and ,但细节让它有所不同。

我的输入日志文件如下所示:

TEMP MON -=- Sat Aug 15 02:20:24 EEST 2020 -=- 48.6
TEMP MON -=- Sat Aug 15 02:20:50 EEST 2020 -=- 49.1
TEMP MON -=- Sat Aug 15 02:21:13 EEST 2020 -=- 49.1
TEMP MON -=- Sat Aug 15 02:21:44 EEST 2020 -=- 49.1
TEMP MON -=- Sat Aug 15 02:21:45 EEST 2020 -=- 48.6
TEMP MON -=- Sat Aug 15 02:21:52 EEST 2020 -=- 49.1
TEMP MON -=- Sat Aug 15 02:21:53 EEST 2020 -=- 48.6
TEMP MON -=- Sat Aug 15 02:21:54 EEST 2020 -=- 49.6
TEMP MON -=- Sat Aug 15 02:21:56 EEST 2020 -=- 49.1
TEMP MON -=- Sat Aug 15 02:21:57 EEST 2020 -=- 49.1

输出应该如下所示:

TEMP MON -=- 2020-08-15_02:20:24 EEST -=- 48.6
...

因此,使用

更改 bash 中的日期格式非常简单
date -d ${date_in_current_format} "+DATE_IN_NEW_FORMAT"

也可以(尽管效率低下)使用 while 循环遍历日志文件并逐行更改日期(再次参见第一个 link)。

但是,我正在寻找一个 bash 解决方案,该解决方案使用 sedperl(或 awk 或与此相关的任何其他内容)来执行相同的操作任务。

我试过但仍然不起作用的提示是以下搜索和替换功能:

perl -pe "s/(.*) -=- (.*) -=- (.*)/ -=- $( date  "+%Z %Y-%m-%d_%H:%M:%S" ) -=- /" <file>

sed 类似:

sed "s:\(.*\) -=- \(.*\) -=- \(.*\): -=- $( date -d  "+%Z %Y-%m-%d_%H:%M:%S" ) -=- :" <file>

在这两种情况下,问题是我无法在 bash date 命令执行中扩展搜索和替换替换“\2”。

您可以使用这个 awk 解决方案:

awk 'BEGIN {
   FS=OFS=" -=- "
}
{
   cmd = sprintf("TZ=EET date -d \"%s\" +\"%Y-%m-%%d_%T %Z\"", );
   if ((cmd | getline output) > 0)
       = output
   close(cmd)
} 1' file
TEMP MON -=- 2020-08-15_02:20:24 EEST -=- 48.6
TEMP MON -=- 2020-08-15_02:20:50 EEST -=- 49.1
TEMP MON -=- 2020-08-15_02:21:13 EEST -=- 49.1
TEMP MON -=- 2020-08-15_02:21:44 EEST -=- 49.1
TEMP MON -=- 2020-08-15_02:21:45 EEST -=- 48.6
TEMP MON -=- 2020-08-15_02:21:52 EEST -=- 49.1
TEMP MON -=- 2020-08-15_02:21:53 EEST -=- 48.6
TEMP MON -=- 2020-08-15_02:21:54 EEST -=- 49.6
TEMP MON -=- 2020-08-15_02:21:56 EEST -=- 49.1
TEMP MON -=- 2020-08-15_02:21:57 EEST -=- 49.1

由于 awk 仅使用字符串函数,您可以避免调用 GNU awk 日期时间函数或外部命令 date,因为我们只想修改月份和 re-order数据。

> cat tst.awk
BEGIN { OFS=FS="-=-" }
{
    split(, arr, " ")
    m=(index("JanFebMarAprMayJunJulAugSepOctNovDec", arr[2])+2)/3
    =sprintf(" %04d-%02d-%02d_%s %s ", arr[6], m, arr[3], arr[4], arr[5])
    print
}

用法:

> awk -f tst.awk file
TEMP MON -=- 2020-08-15_02:20:24 EEST -=- 48.6
TEMP MON -=- 2020-08-15_02:20:50 EEST -=- 49.1
TEMP MON -=- 2020-08-15_02:21:13 EEST -=- 49.1
TEMP MON -=- 2020-08-15_02:21:44 EEST -=- 49.1
TEMP MON -=- 2020-08-15_02:21:45 EEST -=- 48.6
TEMP MON -=- 2020-08-15_02:21:52 EEST -=- 49.1
TEMP MON -=- 2020-08-15_02:21:53 EEST -=- 48.6
TEMP MON -=- 2020-08-15_02:21:54 EEST -=- 49.6
TEMP MON -=- 2020-08-15_02:21:56 EEST -=- 49.1
TEMP MON -=- 2020-08-15_02:21:57 EEST -=- 49.1

在 Perl 中使用核心模块 Time::Piece

perl -MTime::Piece -pe 's/-=-\s+\K(.*)(?=\s+-=-)/convert()/e;
  sub convert {
    $s = $_[0];
    $s =~ s/\s+EEST\s+/ /;
    $t = Time::Piece->strptime($s, "%a %b %d %T %Y");
    $res = $t->strftime("%Y-%m-%d_%H:%M:%S");
    "$res EEST"
 }' file