我有一个像这样的输入数据文件,其中的列名不包含在数据文件中(Date
,,,):Desc
Timestamp1
Timestamp2
2016-01-01, AAA, 330, 1430
2016-01-02, ABA, 130, 930
我需要这样的输出:
2016-01-01, AAA, 2016-01-01 03:30, 2016-01-01 14:30
2016-01-02, ABA, 2016-01-02 01:30, 2016-01-02 09:30
如何才能做到这一点?
答案1
它可以像下面使用一样通过简单的字符串替换来完成awk
,但请注意,如果格式稍有变化或输入数据无效,则此方法可能不太可靠。
awk -F, '/,/{printf "%s, %s, %s %02d:%02d, %s %02d:%02d\n",$1,$2,$1,int($3/100),$3%100,$1,int($4/100),$4%100}' YOUR_FILE.CSV
或者对awk
代码进行格式化以提高可读性:
/,/ {
printf "%s, %s, %s %02d:%02d, %s %02d:%02d\n",
$1, $2,
$1, int($3 / 100), $3 % 100,
$1, int($4 / 100), $4 % 100
}
用简单的英语来说,这将在包含逗号的每一行上运行(以避免处理空行)并仅-F,
使用指定的格式打印出相应的列值(由于输入以逗号分隔):
- 第一列(日期),逗号,第二列(降序),逗号,
- 第 1 列(日期)、第 3 列值 / 100(时间戳 1 的小时)、冒号、第 3 列值模 100(时间戳 1 的分钟)、逗号
- 第 1 列(日期)、第 4 列值 / 100(时间戳 2 的小时数)、冒号、第 4 列值模 100(时间戳 2 的分钟数)
您输入的数据的结果将是
2016-01-01, AAA, 2016-01-01 03:30, 2016-01-01 14:30
2016-01-02, ABA, 2016-01-02 01:30, 2016-01-02 09:30
答案2
您可以使用awk
来实现所需的输出。我不确定输入和输出之间的空白行是否真的存在或只是格式问题,但我在命令中考虑了它们。
awk -F, '{if (NF) { print $1 "," $2 ", " $1 " " sprintf("%02d", int($3 / 100)) ":" $3 % 100 ", " $1 " " sprintf("%02d", int($4 / 100)) ":" $4 % 100 } else { print }}' < input.txt > output.txt
其作用如下:
-F,
将输入字段分隔符设置为awk
,,
以便正确拆分输入。if (NF)
检查输入字段的数量是否大于零。这是为了处理空行。如果该行是空的,则else
命令末尾的部分将打印一个空行。print
命令打印指定的字段:$1
是输入的第一个字段,即日期","
打印文字逗号$2
是第二个字段,描述", "
打印下一个逗号$1
再次打印日期作为时间戳" "
在日期和时间之间添加空格sprintf("%02d", int($3 / 100))
首先通过将时间除以 100 来计算时间的小时部分,丢弃小数(int()
这样做)并打印带有前导零的两位数字(%02d%
作为sprintf()
处理的格式字符串)":"
又是一个冒号$3 % 100
是取模运算,将时间除以 100 得到余数,从而得到分钟数", " $1 " " sprintf("%02d", int($4 / 100)) ":" $4 % 100
第二个时间戳也一样
else
部分内容已在上面用 进行了说明if
。< input.txt
告诉 shellawk
从指定文件读取输入。> output.txt
告诉 shell 将awk
输出写入该文件。
答案3
这是一个 perl 变体(其s/pattern/replacement/
具有e
允许在替换中评估表达式的修饰符):
perl -F', ' -lpe '$_ = join ",", @F[0,1], map {
s/(\d?\d)(\d\d)/sprintf "%s %02d:%02d", $F[0], $1, $2/e ; $_
} @F[2,3] if @F
' file
2016-01-01, AAA, 2016-01-01 03:30, 2016-01-01 14:30
2016-01-02, ABA, 2016-01-02 01:30, 2016-01-02 09:30
答案4
遵循 Perl 版本,采用获取基本元素并重新格式化的策略
perl -ne '/((.*?),.*?, )(\d*)(\d\d), (\d*)(\d\d)/ and
printf("%s%s %02d:%s, %s %02d:%s\n", $1,$2,$3,$4,$2,$5,$6)'