如何将列中的日期转换为bash中的纪元时间戳?

时间:2018-08-02 22:25:47

标签: bash unix awk

我有一个包含以下内容的文件:

2014-11-10 02:00:03,LOGIN SUCCESS,AUTH,user2,192.168.203.63,10.146.124.73,59996,22
2014-11-10 02:00:07,LOGIN SUCCESS,AUTH,user1,172.24.31.10,172.32.1.1,48191,22
2014-11-10 02:00:11,LOGIN FAILED,AUTH,root,172.24.166.153,10.146.124.73,52506,22

我想将时间戳转换为以下格式的日期:

1415602803,LOGIN SUCCESS,AUTH,user2,192.168.203.63,10.146.124.73,59996,22
1415602807,LOGIN SUCCESS,AUTH,user1,172.24.31.10,172.32.1.1,48191,22
1415602811,LOGIN FAILED,AUTH,root,172.24.166.153,10.146.124.73,52506,22

如何使用awk或任何其他bash工具实现这一目标。

背景: 我需要在特定时间范围内从hdfs抓取文件。最初,我是使用 hdfs dfs -stat 带来时间,然后编写过滤器

cat <fileWithFilePaths> | xargs -I ^ -P 15 sh -c 'printf "%s\n" "$(hdfs dfs -stat "%n,%Y,%b" ^)"'>output1

awk 'BEGIN{beginDE=ENVIRON["beginDataEpoch"]; endDE=ENVIRON["endDataEpoch"]; FS="@"} {if ($1 >= beginDE && $1 <= endDE) print $0}' output1

但是后来意识到使用hdfs stat是昂贵的功能。因此,现在我正在使用 hdfs dfs -ls 来增加文件时间,但采用yyyy-mm-dd hh:mm格式,因此我正在寻求帮助以缩短时间以减少计算时间线。

4 个答案:

答案 0 :(得分:2)

如果您的日志文件很大,那么此GNU awk命令将比bash循环为每一行调用外部命令date的速度快得多:

gawk -vFS=, -vOFS=, '{ $1 = mktime(gensub("[-:]", " ", "g", $1)) } 1'
  • 第一个逗号分隔的字段被mktime的结果所代替,gensub是一个函数(GNU扩展名),其返回的参数为自EPOCH以来的秒数。
  • YYYY-MM-DD hh:mm:ss(GNU扩展名)用于将“ YYYY MM DD hh mm ss”转换为“ mktime()”所期望的格式“ 1”。
  • 最后的AppDelegate仅是输出行的TRUE条件。

答案 1 :(得分:1)

您可以使用awk及其内置的gensubmktimesub来完成同一件事,例如

$ awk -F, '{ str=$0; sub($1, mktime(gensub(/[-:]/, " ", "g", $1)), str); print str }' file
1415606403,LOGIN SUCCESS,AUTH,user2,192.168.203.63,10.146.124.73,59996,22
1415606407,LOGIN SUCCESS,AUTH,user1,172.24.31.10,172.32.1.1,48191,22
1415606411,LOGIN FAILED,AUTH,root,172.24.166.153,10.146.124.73,52506,22

说明:

  • gensub(/[-:]/, " ", "g", $1)-用空格替换第一个字段中的所有'-'':'
  • mktime(...)-将生成的日期转换为时间戳;
  • str=$0; sub($1, ..., str);-用时间戳替换第一个字段,结果为str;最后
  • print str-打印。

注意:您的时区和我的时区不同3小时。您的输出应会在系统上为您提供所需的结果。您还可以调整mktime的夏令时(如果需要) ),您可以将内置的strftimeutc-flag配合使用以调整UTC。)

答案 2 :(得分:0)

我想读循环是最简单的。 以下:

while IFS=, read -r date rest; do
        printf "%s,%s\n" "$(date --date="$date" +%s)" "$rest"
done <<EOF
2014-11-10 02:00:03,LOGIN SUCCESS,AUTH,user2,192.168.203.63,10.146.124.73,59996,22
2014-11-10 02:00:07,LOGIN SUCCESS,AUTH,user1,172.24.31.10,172.32.1.1,48191,22
2014-11-10 02:00:11,LOGIN FAILED,AUTH,root,172.24.166.153,10.146.124.73,52506,22
EOF

将输出:

1415581203,LOGIN SUCCESS,AUTH,user2,192.168.203.63,10.146.124.73,59996,22
1415581207,LOGIN SUCCESS,AUTH,user1,172.24.31.10,172.32.1.1,48191,22
1415581211,LOGIN FAILED,AUTH,root,172.24.166.153,10.146.124.73,52506,22

答案 3 :(得分:0)

当我需要在一些历史库存数据中将日期转换为unix时间时,我遇到了同样的问题。使用了此seddate命令。请注意,这仅适用于Linux(seddate的GNU实现)。

simon@debian:~/Downloads$ cat inputFile
2014-11-10 02:00:03,LOGIN SUCCESS,AUTH,user2,192.168.203.63,10.146.124.73,59996,22
2014-11-10 02:00:07,LOGIN SUCCESS,AUTH,user1,172.24.31.10,172.32.1.1,48191,22
2014-11-10 02:00:11,LOGIN FAILED,AUTH,root,172.24.166.153,10.146.124.73,52506,22
simon@debian:~/Downloads$
simon@debian:~/Downloads$
simon@debian:~/Downloads$
simon@debian:~/Downloads$ sed 's/20[0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]/echo `date --date="&" +"%s"`/e' inputFile > output
simon@debian:~/Downloads$
simon@debian:~/Downloads$
simon@debian:~/Downloads$
simon@debian:~/Downloads$ cat output 
1415602803,LOGIN SUCCESS,AUTH,user2,192.168.203.63,10.146.124.73,59996,22
1415602807,LOGIN SUCCESS,AUTH,user1,172.24.31.10,172.32.1.1,48191,22
1415602811,LOGIN FAILED,AUTH,root,172.24.166.153,10.146.124.73,52506,22