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

问题描述

这不是herehere的新问题,但细节使它有所不同。

我的输入日志文件如下:

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循环遍历日志文件并逐行更改日期(再次参见第一个链接)。

但是,我正在寻找一种使用sedperl(或awk或其他任何方式)来执行同一任务的bash解决方案。

我尝试过但仍然无法使用的提示是以下搜索和替换功能:

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

并使用sed类似:

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

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

解决方法

awk仅使用字符串函数的情况下,您可以避免调用GNU awk日期时间函数或外部命令date,因为我们只想修改月份并重新排序数据

> cat tst.awk
BEGIN { OFS=FS="-=-" }
{
    split($2,arr," ")
    m=(index("JanFebMarAprMayJunJulAugSepOctNovDec",arr[2])+2)/3
    $2=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
,

您可以使用以下awk解决方案:

awk 'BEGIN {
   FS=OFS=" -=- "
}
{
   cmd = sprintf("TZ=EET date -d \"%s\" +\"%Y-%m-%%d_%T %Z\"",$2);
   if ((cmd | getline output) > 0)
      $2 = 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
,

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

perl -MTime::Piece -pe 's/-=-\s+\K(.*)(?=\s+-=-)/convert($1)/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

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...