AWK字符串/子字符串操作会丢失原始格式

时间:2014-06-13 17:10:37

标签: bash shell awk scripting gawk

您好我有以下文件:

P:TWS.XAUUSD    07:34:47.872000 0       1306.73 1000    1306.87 500     0       0       99
P:TWS.XAUUSD    07:34:47.876000 0       1306.7  500     1306.87 500     0       0       99
P:TWS.XAUUSD    07:34:47.877000 0       1306.7  500     1306.85 500     0       0       99

我想更改第二列中的时间戳($ 2)并将其缩短1小时。

我使用awk,并将第二个字段拆分为两个单独的子字符串,但是当我使用以下代码时:

awk '{print $1,substr($2,1,2)-1 substr($2,3,13),$3,$4,$5,$6,$7,$8,$9,$10}'

我的输出看起来像这样

P:TWS.XAUUSD 6:34:47.872000 0 1306.73 1000 1306.87 500 0 0 99
P:TWS.XAUUSD 6:34:47.876000 0 1306.7 500 1306.87 500 0 0 99
P:TWS.XAUUSD 6:34:47.877000 0 1306.7 500 1306.85 500 0 0 99

计算和信息是正确的,但我正在丢失格式(我要求小时HH列为2位)。

如何执行相同的计算并保留原始格式。

我尝试使用 printf 命令,但是我似乎无法提取多个字段,并获得我需要的整行。

  

awk' {printf("%02d \ n"),$ 2-1}'

给我以下输出

06
06
06

如何将打印 printf 放在一起?

5 个答案:

答案 0 :(得分:4)

特定于gawk的解决方案,保留原始的精确间距:

gawk 'BEGIN {FIELDWIDTHS = "16 2 72"}{printf("%s%02d%s\n", $1, ($2-1>0?$2-1:23), $3)}' file

当然,使用子串也可以轻松完成同样的事情。

答案 1 :(得分:2)

我建议使用awk的时间函数进行算术运算:

awk '
    BEGIN { date = strftime("%Y %m %d", systime()) }
    {
        split($2, a, /[:.]/)
        t = mktime(date" "a[1]-1" "a[2]" "a[3])
        $2 = strftime("%T",t) "." a[4]
        print
    }
' file

当时间为" 00:00:00"时,这有利于将时间打印为" 23:00:00"而不是" -1:00:00"

每年有几个小时(夏令时过渡),这种过于简单的算法会产生错误的结果。

答案 2 :(得分:1)

使用OFS='\t'(输出字段分隔符):

awk '{print $1,substr($2,1,2)-1 substr($2,3,13),$3,$4,$5,$6,$7,$8,$9,$10}' OFS='\t' file
P:TWS.XAUUSD    6:34:47.872000  0   1306.73 1000    1306.87 500 0   0   99
P:TWS.XAUUSD    6:34:47.876000  0   1306.7  500 1306.87 500 0   0   99
P:TWS.XAUUSD    6:34:47.877000  0   1306.7  500 1306.85 500 0   0   99

答案 3 :(得分:1)

如果您可以使用perl,那么:

$ cat file
P:TWS.XAUUSD    07:34:47.872000 0       1306.73 1000    1306.87 500     0       0       99
P:TWS.XAUUSD    07:34:47.876000 0       1306.7  500     1306.87 500     0       0       99
P:TWS.XAUUSD    07:34:47.877000 0       1306.7  500     1306.85 500     0       0       99

$ perl -pe 's/(\d+)/sprintf "%02d", ($1-1>0?$1-1:23)/e' file
P:TWS.XAUUSD    06:34:47.872000 0       1306.73 1000    1306.87 500     0       0       99
P:TWS.XAUUSD    06:34:47.876000 0       1306.7  500     1306.87 500     0       0       99
P:TWS.XAUUSD    06:34:47.877000 0       1306.7  500     1306.85 500     0       0       99

答案 4 :(得分:0)

您也可以将输出传递给列命令

[nabeel@nmoidu ~]$ awk '{print $1,substr($2,1,2)-1 substr($2,3,13),$3,$4,$5,$6,$7,$8,$9,$10}' test | column -t
P:TWS.XAUUSD  6:34:47.872000  0  1306.73  1000  1306.87  500  0  0  99
P:TWS.XAUUSD  6:34:47.876000  0  1306.7   500   1306.87  500  0  0  99
P:TWS.XAUUSD  6:34:47.877000  0  1306.7   500   1306.85  500  0  0  99