【问题标题】:Awk exctracting column but just from one rowawk 提取列但仅从一行
【发布时间】:2020-01-27 14:19:23
【问题描述】:

我有一个格式如下的脚本:

2017-12-11 10:20:16.993 ...

2017-12-12 10:19:16.993 ...

2017-12-13 10:17:16.993 ...

我想通过 awk - F. 提取第一列,并将其与实际系统时间(以秒为单位)进行比较,如果差异小于 300 秒,则打印该行。

>   SYSTEM_TIME=$(date +%s)
>                 awk -F. -v system_time=$SYSTEM_TIME '{gsub(/[-:]/," ",$1); if(system_time-mktime($1) <= 300) {print $0}}' log.txt

这是我的代码,但我不能使用 mktime,因为它不在 POSIX 规范中。没有它可以吗?

谢谢,

艾哈迈德

【问题讨论】:

    标签: bash shell awk


    【解决方案1】:

    一般说明:日志文件通常不完整。给出了日期时间格式,但通常缺少时区。当夏令时开始发挥作用时,如果您错过了您的时区,它可能会破坏您的全部业力。


    注意:在以下所有命令中,将假定日志文件中的日期为 UTC,并且系统以 UTC 运行。如果不是这种情况,请注意夏令时会在夏令时开始时运行以下任何命令时产生问题。


    dateawk 的组合:(不是 POSIX)

    如果您的 date 命令具有 -d 标志(不是 POSIX),您可以运行以下命令:

    awk -v r="(date -d '300 seconds ago' '+%F %T.%3N)" '(r < $0)'
    

    仅限 GNU awk:

    如果你想使用mktime,那就更简单了:

    awk 'BEGIN{s=systime();FS=OFS="."}
         {t=$1;gsub(/[-:]/," ",t); t=mktime(t)}
         (t-s < 300)' logfile
    

    我会假设将来不会创建日志文件,所以所有时间总是小于系统时间。

    POSIX:

    如果您不能使用mktime,但只想使用posix,这也意味着date 没有-d 标志,您可以创建自己的mktime 实现。请注意,此处提供的版本不会像 mktime 那样进行任何时区更正。 mktime_posix 假定 datestring 是 UTC

    awk -v s="$(date +%s)" '
    # Algorithm from "Astronomical Algorithms" By J.Meeus
    function mktime_posix(datestring,    a,t) {
        split(datestring,a," ")
        if (a[1] < 1970) return -1
        if (a[2] <= 2) { a[1]--; a[2]+=12 }
        t=int(a[1]/100); t=2-t+int(t/4)
        t=int(365.25*a[1]) + int(30.6001*(a[2]+1)) + a[3] + t - 719593
        return t*86400 + a[4]*3600 + a[5]*60 + a[6]
    }
    BEGIN{FS=OFS="."}
    {t=$1;gsub(/[-:]/," ",t); t=mktime_posix(t)}
    (t-s <= 300)' logfile
    

    相关:this answerthis answer

    【讨论】:

    • 但是我不能使用 mktime。
    • 当我在相同的时间戳上运行 mktime()mktime_posix() 时,我得到的值非常不同。 mktime() 值与 date +%s -d 值一致。看起来这是一个区域设置问题,因为他们已经关闭了 6 小时,而我的 TZ 比格林威治标准时间晚了 6 小时。
    • @EdMorton mktime_posix 假定 TZ 是 UTC。 mktime 进行时区校正。您可以尝试使用TZ=UTC awk '...' 运行它
    • 是的,可以的。也许只是将其添加到您的答案中?
    • 您是否有会产生问题的时间戳示例?我在 DST 开始之前、之后和之后尝试了第二个,在我的 TZ 中结束并且没有问题,但我认为有时会有一个......我对这个解决方案很感兴趣,因为如果它运行良好,它会解决一个常见问题,而无需通常的性能打击。
    【解决方案2】:

    我认为这样做会更短。

    #!/bin/bash
    
    SYSTEM_TIME=$(date +%s)
    LOGTIME=$( date "+%s" -d "$( awk -F'.'  '{print $1}' <( head -1 inputtime.txt ))" )
    DIFFERENCEINSECONDS=$( echo "$SYSTEM_TIME $LOGTIME" | awk '{ print ($1 - $2)}' )
    
    if [[ "$DIFFERENCEINSECONDS" -gt 300 ]]
    then
        echo "TRIGGERED!"
    fi
    

    希望它对您有用。告诉我。

    注意:我假设您的输入日志可以称为 inputtime.txt。当然,您需要更改您的实际文件名。

    【讨论】:

      猜你喜欢
      • 2018-06-16
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-30
      • 2013-11-27
      • 1970-01-01
      相关资源
      最近更新 更多