【问题标题】:Round down to nearest quarter hour using AWK w/ file input使用带有/文件输入的 AWK 向下舍入到最接近的一刻钟
【发布时间】:2014-01-18 05:29:41
【问题描述】:

我有一个逗号分隔的文件,其中一个字段包含以下格式的日期时间:

2014 年 1 月 15 日 13:53

我需要将此字段的时间部分向下舍入到最接近的一刻钟。我可以让 awk 仅使用日期/时间作为输入来执行舍入,但我无法让 awk 读取文件并执行舍入。这是用于将日期/时间四舍五入作为直接输入的 awk 命令:

echo "04/17/2014 12:59" | awk '{split($2, a, ":"); printf "%s %s:%02d", $1, a[1],int(a[2]/15)*15}'

我将如何使用整个文件作为输入来执行相同的舍入,其中日期/时间是逗号分隔文件中的第三个字段?

【问题讨论】:

  • 基本相同。您仍然可以使用您的split: 之后的部分进行操作,主要区别在于您想要拆分$3 字段并且您想要将您的结果a[1],int(...) 分配回$3 然后print.
  • @EtanReisner 您如何将结果分配回 $3。类似 - $3=printf .... 还是需要将其括在 () 中?
  • 基本上就像我说的:$3=a[1],int(...).

标签: shell unix awk


【解决方案1】:

使用perl 会简洁明了:

$ echo "04/17/2014 12:59" | perl -pe 's|(?<=:)\d\d\b|int($&/15)*15|ge'
04/17/2014 12:45

解释:

  • perl-pe 标志是为每一行运行表达式,可能会对其进行修改,然后打印结果行,其行为类似于sedawk
  • (?&lt;=:)\d\d\b 表达式匹配: 后面的两个数字,但不包括匹配模式中的:(零宽度正向后视)。 \b 标记了一个单词边界,所以它不会匹配 ":123"
  • 替换中的$&amp; 是匹配的模式,在本例中为 59
  • s///e 命令中的 e 标志用于将替换评估为 perl 脚本,允许对匹配的模式执行 int(... / 15) * 15 算法
  • 我们在s/// 命令中使用| 作为分隔符,而不是/,以便我们可以在替换模式中使用/

【讨论】:

    【解决方案2】:
    awk -F, -v OFS=, '
        function round_time(t,   a) {
            split(t,a,/:/)
            return sprintf("%s:%02d", a[1], int(a[2] / 15)*15)
        }
        {$3 = round_time($3); print}
    ' << END
    a,b,01/15/2014 13:53,d
    e,f,01/15/2014 14:13,h
    END
    
    a,b,01/15/2014 13:45,d
    e,f,01/15/2014 14:00,h
    

    【讨论】:

    • 这行得通,谢谢。你能解释一下函数声明吗?我知道 't' 是输入,但 'a' 和它之前的间距是什么?
    • 如果你不在函数的参数列表中命名变量,那么它们将是全局变量。这是一个 awk 约定,将您希望作为函数本地的所有变量放在参数列表中,并且空格表示要传入的参数与本地变量之间的差异。参考:gnu.org/software/gawk/manual/html_node/Variable-Scope.html
    猜你喜欢
    • 2016-02-26
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多