使用Sed的内部命令和正则表达式组引用

7

我将要解决以下问题:

我有一个文件,其内容如下:

1521471079313,219,HTTP Request 14,200,OK,PROD 50 rpm 1-10,text,true,,17665,204,1,1,177,0,35
1521471080337,263,HTTP Request 11,200,OK,PROD 50 rpm 1-10,text,true,,30268,202,1,1,169,0,0
1521471081404,245,HTTP Request 12,200,OK,PROD 50 rpm 1-10,text,true,,5134,201,1,1,210,0,37
1521471082453,125,HTTP Request 13,200,OK,PROD 50 rpm 1-10,text,true,,8910,201,1,1,106,0,0
1521471083381,217,HTTP Request 14,200,OK,PROD 50 rpm 1-10,text,true,,17665,204,1,1,188,0,0
1521471084402,303,HTTP Request 11,200,OK,PROD 50 rpm 1-10,text,true,,30268,202,1,1,226,0,41
  • 列表中的第一项是epoc时间戳,我想将其转换为可读格式。
  • 我尝试了以下命令:
cat file.csv|sed -E  "s/^([0-9]*)(,.*)/$(date -r \1 '+%m-%d-%Y:%H:%M:%S')\2/p"

看起来它可以工作,但是我发现它会将其转换为:

01-01-1970:01:00:01,245,HTTP Request 13,200,OK,PROD 50 rpm 1-10,text,true,,8910,201,1,1,219,0,43
01-01-1970:01:00:01,276,HTTP Request 14,200,OK,PROD 50 rpm 1-10,text,true,,17665,204,1,1,217,0,0
01-01-1970:01:00:01,276,HTTP Request 14,200,OK,PROD 50 rpm 1-10,text,true,,17665,204,1,1,217,0,0
01-01-1970:01:00:01,242,HTTP Request 11,200,OK,PROD 50 rpm 1-10,text,true,,30268,202,1,1,216,0,34
01-01-1970:01:00:01,242,HTTP Request 11,200,OK,PROD 50 rpm 1-10,text,true,,30268,202,1,1,216,0,34
01-01-1970:01:00:01,147,HTTP Request 12,200,OK,PROD 50 rpm 1-10,text,true,,5134,201,1,1,119,0,0
01-01-1970:01:00:01,147,HTTP Request 12,200,OK,PROD 50 rpm 1-10,text,true,,5134,201,1,1,119,0,0

所有的时间戳都看起来像是“时光之初 :-)”,而不是我想要的格式。
我知道在sed命令中有一个命令替换,并且还有两个基于前面正则表达式的组引用,但为什么它不起作用让我感到困惑。
2个回答

7
你可以使用GNU awk 轻松解析CSV文件。你的$1 值是毫秒级的EPOCH值。你可以在将该值除以1000(即转换为秒)后使用strftime()调用打印可读性更好的格式。
awk 'BEGIN{FS=OFS=","}{$1=strftime("%c",($1/1000))}1' file

对于原地编辑,请使用gawk或将输出移动到临时文件并将其恢复为原始文件。

tmpfile=$(mktemp /tmp/abc.XXXXXX)
awk 'BEGIN{FS=OFS=","}{$1=strftime("%c",($1/1000))}1' file > "$tmpfile"
mv "$tmpfile" file

2
这是正确的方法。 - Matias Barrios
可能是正确的,但问题实际上是关于sed的,因为我也想知道如何在sed的内部命令中让组引用起作用。而且strftime似乎在macOS上不起作用awk:调用未定义的函数strftime - Ivonet
1
安装了gawk后,我的Mac正常工作了!虽然@user-unknown的答案更接近我的问题,但我还是要感谢他,因为那个答案也很好用,尽管有点“dirty-er”。谢谢! - Ivonet
@Ivonet:干杯!没问题。 - Inian

1
这对我有效:

sed -r "s/^([0-9]+)(,.*)/echo \$(date -d @\1)\2/" sampl3.log > log.sh && bash log.sh  

但是你必须确保日志中不包含恶意命令,并且调整日期格式以保证安全。

Mi 2. Jul 01:21:53 CEST 50183,219,HTTP Request 14,200,OK,PROD 50 rpm 1-10,text,true,,17665,204,1,1,177,0,35
Mi 2. Jul 01:38:57 CEST 50183,263,HTTP Request 11,200,OK,PROD 50 rpm 1-10,text,true,,30268,202,1,1,169,0,0
Mi 2. Jul 01:56:44 CEST 50183,245,HTTP Request 12,200,OK,PROD 50 rpm 1-10,text,true,,5134,201,1,1,210,0,37
Mi 2. Jul 02:14:13 CEST 50183,125,HTTP Request 13,200,OK,PROD 50 rpm 1-10,text,true,,8910,201,1,1,106,0,0
Mi 2. Jul 02:29:41 CEST 50183,217,HTTP Request 14,200,OK,PROD 50 rpm 1-10,text,true,,17665,204,1,1,188,0,0
Mi 2. Jul 02:46:42 CEST 50183,303,HTTP Request 11,200,OK,PROD 50 rpm 1-10,text,true,,30268,202,1,1,226,0,41

这是在我杀掉时间戳的最后三位后实际为我工作的命令:sed -E "s/^([0-9]{10})[0-9]{3}(,.*)/echo \$(date -r \1 '+%m-%d-%Y:%H:%M:%S')\2/" rpm_50_prod_res.csv > log.sh && bash log.sh 这是因为你提供的一些参数在 Mac 上不起作用...忘了告诉你。 - Ivonet
我的印象是,具体的日期格式和sed语法都不是问题,而是sed函数中\1的评估时间出了问题,导致它无法正常工作。 - user unknown

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接