在 csv 文件的第三列中将秒数转换为年龄

Posted

技术标签:

【中文标题】在 csv 文件的第三列中将秒数转换为年龄【英文标题】:Convert seconds to age in 3rd column of csv file 【发布时间】:2015-11-10 16:18:04 【问题描述】:

逗号分隔的 csv 文件的第三列包含我想转换为年龄的秒数。 (下面的示例数据)。我正在使用 bash 生成这些报告,并希望将秒数转换为 10d 3h 20min 30sec 或类似的时间。有没有简单的方法可以做到这一点?

谢谢

28126265
6678363
3182862
11401914
1029092
9655690
34381431
13126178
2516335

【问题讨论】:

您是在寻找剧本还是一个班轮? 一个我可以添加到我现有脚本中的衬里会很好...... 【参考方案1】:

使用 Perl:

perl -F, -ane 'printf "%dd %dh %dm %ds\n", int($F[2]/(24*60*60)), ($F[2]/(60*60))%24, ($F[2]/60)%60, $F[2]%60' file

-a 将每一行自动拆分为数组 @F-F, 使用逗号作为分隔符自动拆分每一行 由于 Perl 数组从索引 0 开始,第三个元素是 $F[2]

输入:

a,b,28126265,d,e
a,b,6678363,d,e
a,b,3182862,d,e
a,b,11401914,d,e
a,b,1029092,d,e
a,b,9655690,d,e
a,b,34381431,d,e
a,b,13126178,d,e
a,b,2516335,d,e

输出:

325d 12h 51m 5s
77d 7h 6m 3s
36d 20h 7m 42s
131d 23h 11m 54s
11d 21h 51m 32s
111d 18h 8m 10s
397d 22h 23m 51s
151d 22h 9m 38s
29d 2h 58m 55s

由于您要保留现有数据:

perl -F, -ane 'printf "%s,%dd %dh %dm %ds,%s", (join ",",@F[0..1]), int($F[2]/(24*60*60)), ($F[2]/(60*60))%24, ($F[2]/60)%60, $F[2]%60, (join ",",@F[3..$#F])' file

@F[0..1]是数组@F前两个元素的数组切片$#F是数组@F最后一个元素的索引

输出:

a,b,325d 12h 51m 5s,d,e
a,b,77d 7h 6m 3s,d,e
a,b,36d 20h 7m 42s,d,e
a,b,131d 23h 11m 54s,d,e
a,b,11d 21h 51m 32s,d,e
a,b,111d 18h 8m 10s,d,e
a,b,397d 22h 23m 51s,d,e
a,b,151d 22h 9m 38s,d,e
a,b,29d 2h 58m 55s,d,e

或者:

perl -F, -ane '$F[2] = sprintf "%dd %dh %dm %ds", int($F[2]/(24*60*60)), ($F[2]/(60*60))%24, ($F[2]/60)%60, $F[2]%60; print join ",",@F' file

【讨论】:

这正是我想要的。它在格式化第三列时保持所有其他列不变...感谢您的帮助...【参考方案2】:

除非您愿意使用 Perl 或 Python,否则它不会是单行的。

在 awk 中,(我不擅长)这里有一个解决方案。

给定:

$ echo "$ages"
28126265
6678363
3182862
11401914
1029092
9655690
34381431
13126178
2516335

你可以这样做:

echo "$ages" | awk '
t=int($0);
days=int(t/(24*60*60));
t-=days*24*60*60;
hours=int(t/(60*60));
t-=hours*60*60;
minutes=int(t/60);
seconds=int(t-minutes*60);
printf("%dd %02dh %02dm %02ds\n", days, hours, minutes, seconds);'

打印:

325d 12h 51m 05s
77d 07h 06m 03s
36d 20h 07m 42s
131d 23h 11m 54s
11d 21h 51m 32s
111d 18h 08m 10s
397d 22h 23m 51s
151d 22h 09m 38s
29d 02h 58m 55s

【讨论】:

我可以管理这样的事情。我的问题是这些数据(在您的示例中为 $ages)是大型报告的一部分。它是 csv 文件中的第三列。所以我需要一种方法来更改数据或写入新文件但仍保留报告的其余部分.. 我不确定我是否理解您的要求。但是我使用 bash 脚本来组合 3 个不同的报告(由性能应用程序创建),然后在将数据发送给用户之前对其进行处理。 我尝试提取数据并使用您的解决方案对其进行格式化,但我无法将其正确返回到第三列。我用来用临时文件中的格式化数据替换旧数据的 awk 行正在删除我所有的逗号,我不知道为什么。我知道有一种更简单的方法可以实现这一点... awk 'BEGIN FS = "," ; FNR==NRa[NR]=$1;next$3=a[FNR] 1' ./temp/agesconv.csv ./reports/PROD_Age_Report.csv【参考方案3】:

这是一个可能的解决方案。但不是oneliner。

time=28126265
m=60
h=$((m * 60))
d=$((24 * h))
nd=$((time / d))
rt=$((time % d))
nh=$((rt / h))
rt=$((rt % h))
nm=$((rt / m))
rt=$((rt % m))
echo $ndd $nhh $nmm $rts  

【讨论】:

【参考方案4】:

这是另一种方式

awk -v FS="[,]+" 'days=$3/86400;hours=(days-int(days))*24;minutes=(hours-int(hours))*60;seconds=(minutes-int(minutes))*60;print int(days)"d",int(hours)"h",int(minutes)"m",int(seconds)"s"'

这里是分类

awk -v FS="[,]+" '
days=$3/86400; #find floating value for days
hours=(days-int(days))*24; #minus floating value from rounded value and multiply by 24 to get floating value for hours
minutes=(hours-int(hours))*60; #minus floating value of hours from rounded value and multiply by 60 to get floating value for minutes
seconds=(minutes-int(minutes))*60; #minus floating value of minutes from rounded value and multiply by 60 to get floating value for seconds
print int(days)"d",int(hours)"h",int(minutes)"m",int(seconds)"s"
'

输出

325d 12h 51m 4s
77d 7h 6m 3s
36d 20h 7m 41s
131d 23h 11m 53s
11d 21h 51m 32s
111d 18h 8m 10s
397d 22h 23m 50s
151d 22h 9m 37s
29d 2h 58m 55s

【讨论】:

请注意,我使用 $3 让 awk 处理文件第 3 列中的秒数

以上是关于在 csv 文件的第三列中将秒数转换为年龄的主要内容,如果未能解决你的问题,请参考以下文章

在R中将完整年龄从字符转换为数字

在 Spark Dataframe API 中将出生日期转换为年龄

使用 DictReader 访问 CSV 的第三列时出现 KeyError [重复]

使用jmeter测试的时候,需要读取csv文件的第三列,csv文件名为test.csv,如何使用函数读取?

如何在python中将csv文件导入为numpy.array? [复制]

用 Python 计算 .CSV 文件中的年龄