【问题标题】:Comparing variables in awk比较awk中的变量
【发布时间】:2014-08-28 11:56:34
【问题描述】:

我的文件在其第 6 个字段中有时间戳,如下所示:Mon Jul 7 14:53:16 PDT 2014

我想从该文件中获取所有这些行,其第 6 个字段值在过去 24 小时内

示例输入:

abc -> /aa/bbb, hello, /home/user/blah.pl, 516, usc, Mon Jul 4 10:06:33 PDT 2014
abc -> /aa/bbb, hello, /home/user/blah.pl, 516, usc, Mon Jul 5 10:06:33 PDT 2014
abc -> /aa/bbb, hello, /home/user/blah.pl, 516, usc, Mon Jul 7 07:06:33 PDT 2014 
abc -> /aa/bbb, hello, /home/user/blah.pl, 516, usc, Mon Jul 7 08:06:33 PDT 2014
abc -> /aa/bbb, hello, /home/user/blah.pl, 516, usc, Mon Jul 7 09:06:33 PDT 2014
abc -> /aa/bbb, hello, /home/user/blah.pl, 516, usc, Mon Jul 7 10:06:33 PDT 2014

字段分隔符是逗号。

示例代码 但它没有按预期工作:

awk 'BEGIN {FS = ","};
{ a=$6;
aint=a +"%y%m%d%H%M%S";
yestint=$(date --date='1 day ago' +"%y%m%d%H%M%S");
if (aint>yestint)
print aint;
}' /location/canzee/textfile.txt

样本输出 我得到这样的输出:

awk: cmd. line:4: yestint=$(date --date=1
awk: cmd. line:4:                      ^ syntax error
awk: cmd. line:5: (END OF FILE)
awk: cmd. line:5: syntax error

期望的输出

Mon Jul 7 07:06:33 PDT 2014
Mon Jul 7 08:06:33 PDT 2014
Mon Jul 7 09:06:33 PDT 2014
Mon Jul 7 10:06:33 PDT 2014

如果我不能在 awk 命令中调用诸如 date 之类的 shell 命令,我想知道如何解决这个问题。我希望它足够清楚。

【问题讨论】:

  • $(yest) 应该是 "$yest"。文件中字段 6 的格式是什么? $yest 将类似于 Sun Jul 6 16:26:09 CDT 2014,我不知道您希望如何将其与 < 进行比较。
  • awk -v yest=$yest...
  • 您的变量引用语法已关闭:使用"$yest""${yest}" - $(yest) 不是变量引用,而是命令替换
  • 你觉得跟时间戳的格式有关系吗?您可以显示文件中的示例行吗?
  • 添加一个显示两个值的调试行,由边界字符包围,例如,print "a=|"a"|\tyest=|"yest"|"。其他 cmets 也将被观察 ;-) 祝你好运。

标签: awk


【解决方案1】:

这是一个想法的草图。请注意,它是 gawk 特有的。

# An array to convert abbreviated month names to numbers.
BEGIN {m["Jan"]=1; m["Feb"]=2; m["Mar"]=3; m["Apr"]=4; m["May"]=5; m["Jun"]=6
       m["Jul"]=7; m["Aug"]=8; m["Sep"]=9; m["Oct"]=10; m["Nov"]=11; m["Dec"]=12;}


# later in your script
{

# systime() gives the number of seconds since the "epoch".
# Subtract 24-hours-worth of seconds from it to get "yesterday".
# (Note that this is yesterday at a specific time, which may not
# really be what you want.)
yest = systime() - 24 * 60 * 60;

a = "Mon Jul 7 14:27:56 PDT 2014"   # or however a gets its value

# Split the fields of a into the array f (splitting on spaces).
split(a, f, " ");

# Split the fields of f[4] (the time) into the array t (splitting on colons).
split(f[4], t, ":")

# mktime() converts a date specification into seconds since the epoch.
# The datespec format is: 2014 7 7 14 27 56 [optional dst flag]
# If the daylight savings time flag is left out the system tries to determine
# whether or not dst is in effect.
tm = mktime(f[6] " " m[f[2]] " " f[3] " " t[1] " " t[2] " " t[3])

#Compare the seconds since epochs.
if (tm > yest)
  ...

}

在你的程序的上下文中,它可能是这样完成的:

awk '
  BEGIN {
    m["Jan"]=1; m["Feb"]=2; m["Mar"]=3; m["Apr"]=4; m["May"]=5; m["Jun"]=6
    m["Jul"]=7; m["Aug"]=8; m["Sep"]=9; m["Oct"]=10; m["Nov"]=11; m["Dec"]=12;
    FS = "[[:space:]]*,[[:space:]]*"
    yest = systime() - 24 * 60 * 60;
  }

  {
    split($6, f, " ")
    split(f[4], t, ":")
    tm = mktime(f[6] " " m[f[2]] " " f[3] " " t[1] " " t[2] " " t[3])
    if (tm > yest)
      print $6;
  }
' /location/canzee/textfile.txt

【讨论】:

  • 您应该提到您的脚本是 gawk 特定的。 OP 可能没有使用 GNU awk。
  • 是的。时间函数 (mktime()/systime())、gensub()、PROCINFO[]、asort/asorti() 和真正的多维数组(arr[i][j] 语法与 arr[i,j])是人们使用的典型 gawk 特定功能。我不知道任何地方都有一个保持最新状态的表。
  • @EdMorton 我喜欢这样!打字少了很多。我会保持原样,但我会记住它以备将来使用。谢谢。
  • @Jotne 这是另一种有效的方法,但如何更好?如果是为了避免重复,awk 'function m(n) {return (match("JanFebMarAprMayJunJulAugSepOctNovDec",n)+2)/3} BEGIN{print m("Jun")}' 将是最简单和最简单的添加检查以在一个地方处理无效的月份名称。也许有性能差异?身份证...
  • @EdMorton 忘了function :)
猜你喜欢
  • 1970-01-01
  • 2013-12-31
  • 1970-01-01
  • 2020-03-23
  • 2011-01-06
  • 2019-03-02
  • 2019-01-20
  • 2014-01-27
  • 1970-01-01
相关资源
最近更新 更多