我必须遵循文字:
30/01/2017 00:00:00 158
30/01/2017 00:30:00 158
30/01/2017 01:00:00 158
30/01/2017 01:30:00 158
30/01/2017 02:00:00 158
30/01/2017 02:30:00 158
30/01/2017 03:00:00 158
30/01/2017 03:30:00 158
30/01/2017 04:00:00 158
30/01/2017 04:30:00 158
30/01/2017 05:00:00 158
30/01/2017 05:30:00 158
30/01/2017 06:00:00 158
30/01/2017 06:30:00 157
30/01/2017 07:00:00 157
30/01/2017 07:30:00 157
30/01/2017 08:00:00 157
我希望使用正则表达式以ISO格式重新排序日期并转换为.csv文件。
我对这些命令进行了测试:
perl -pe 's/(\s)([0-9]{2})\/([0-9]{2})\/([0-9]{4})\s([0-9]{2}:[0-9]{2}:[0-9]{2})(\s+)(.*)/$4-$3-$2_$5;$7;931;2/g' file.txt > output.csv
和
sed -E 's/(\s)([0-9]{2})\/([0-9]{2})\/([0-9]{4})\s([0-9]{2}:[0-9]{2}:[0-9]{2})(\s+)(.*)/\4-\3-\2_\5;\7;931;2/g' file.txt > output.csv
预期结果是:
2017-01-30_00:00:00;158;931;2
2017-01-30_00:30:00;158;931;2
2017-01-30_01:00:00;158;931;2
2017-01-30_01:30:00;158;931;2
2017-01-30_02:00:00;158;931;2
2017-01-30_02:30:00;158;931;2
2017-01-30_03:00:00;158;931;2
2017-01-30_03:30:00;158;931;2
2017-01-30_04:00:00;158;931;2
2017-01-30_04:30:00;158;931;2
2017-01-30_05:00:00;158;931;2
2017-01-30_05:30:00;158;931;2
2017-01-30_06:00:00;158;931;2
2017-01-30_06:30:00;157;931;2
2017-01-30_07:00:00;157;931;2
2017-01-30_07:30:00;157;931;2
2017-01-30_08:00:00;157;931;2
但结果是:
;931;21-30_00:00:00;158
;931;21-30_00:30:00;158
;931;21-30_01:00:00;158
;931;21-30_01:30:00;158
;931;21-30_02:00:00;158
;931;21-30_02:30:00;158
;931;21-30_03:00:00;158
;931;21-30_03:30:00;158
;931;21-30_04:00:00;158
;931;21-30_04:30:00;158
;931;21-30_05:00:00;158
;931;21-30_05:30:00;158
;931;21-30_06:00:00;158
;931;21-30_06:30:00;157
;931;21-30_07:00:00;157
;931;21-30_07:30:00;157
;931;21-30_08:00:00;157
注意** 931; 2 **在开头,但它是在最后。甚至吃了2017年的一部分。
为什么会这样?
答案 0 :(得分:4)
问题几乎可以肯定是您使用Linux来处理源自Windows系统的文件,该文件具有CR LF行结尾。正则表达式模式末尾的.*
与每行上最后一个数字(但不是LF)之后的CR匹配,因此将其保留在$7
中并将其插入到输出中。这使;931;2
出现在行的开头,覆盖之前的字符
解决此问题的一种方法是将chomp
替换为s/\R\z//
,它将匹配行尾的CR,LF或CR LF中的任何一个,因此处理任何行的结尾系统
你的正则表达式是正确的,但我只是收集每条记录中的所有数字字段,并使用printf
重新格式化输出。这样就不需要删除在第一个地方结束的行
看起来像这样
use strict;
use warnings 'all';
open my $fh, '<', 'data.txt' or die $!;
while ( <$fh> ) {
my @F = /\d+/ag;
printf "%04d-%02d-%02d_%02d:%02d:%02d;%d;%d;%d\n",
@F[2,1,0,3,4,5,6], 931, 2;
}
2017-01-30_00:00:00;158;931;2
2017-01-30_00:30:00;158;931;2
2017-01-30_01:00:00;158;931;2
2017-01-30_01:30:00;158;931;2
2017-01-30_02:00:00;158;931;2
2017-01-30_02:30:00;158;931;2
2017-01-30_03:00:00;158;931;2
2017-01-30_03:30:00;158;931;2
2017-01-30_04:00:00;158;931;2
2017-01-30_04:30:00;158;931;2
2017-01-30_05:00:00;158;931;2
2017-01-30_05:30:00;158;931;2
2017-01-30_06:00:00;158;931;2
2017-01-30_06:30:00;157;931;2
2017-01-30_07:00:00;157;931;2
2017-01-30_07:30:00;157;931;2
2017-01-30_08:00:00;157;931;2
在单行中,
perl -ne '@F = /\d+/ag; printf "%04d-%02d-%02d_%02d:%02d:%02d;%d;%d;%d\n", @F[2,1,0,3,4,5,6], 931, 2;' myfile
答案 1 :(得分:0)
这可能适合你(GNU sed):
sed -r 's/^.(..).(..).(....).(........)\s*(\S*).*/\3-\2-\1_\4;\5;931;2/' file