【问题标题】:How change date Format column in csv.bz2 and update file in Unix如何更改 csv.bz2 中的日期格式列并在 Unix 中更新文件
【发布时间】:2021-10-04 08:45:05
【问题描述】:

我有一个包含数百万条记录的 bz2 压缩 csv 文件。第一行包含文件头。 我有多个日期列,但只有两个特定列需要更改为 从 yyyy/mm/dd hh24:mm 格式化日期并将其设置为 dd/mm/yy hh24:mm 并更新 csv.bz2 文件。 我正在寻找用 awk 进行研究,用这个

bzcat OBACountryIPTV_CALICUX_Report_Session_Local_Timezone_2021-07-02_000000.csv.bz2 |
head -1 | sed 's /; / \ n / g' | nl

我设法找到了需要重新格式化的列的位置:

  1  playtime
  2  traffic
  .
  .
 30  end_time
 31  start_time
 .
 .
122  playback_id

例如每一行的输出:

0.0;0.0;;0.0;0;;0.0;0;0.0;0.0;7.0;-1.0;0.0;0.0;0;0;0;0;0;0;0;0;0.0;0.0;0.0;;;0.0;0.0;2021/05/11 17:52;2021/05/11 17:52;0.0;Argentina;;;;LATAM;Unknown;WIFI;Undefined;;Undefined;Streaming;TELEFE;N/A - Multicast;;LIVE;;STB;;;;;;;;Not reported;;;29_2255508521_1620777131852;{"channel_id": 3346, "channel_name": "TELEFE", "channel_number": null, "delaytime": null, "dist_id": null, "player_session_name": null, "playtime": null, "program_id": 500508915, "resolution": "HD", "device_version": "2020.06.26.00.08.27", "ip": "10.241.164.84", "ob": "29", "device_type": null, "user_id": "17059165", "device_id": "2255508521", "operation": "LIV/channel-change", "transaction_id": "476707713_2255508521_29", "status": null, "timestamp": "2021-05-11T20:52:11.852-03:00", "bit_rate": "7Mbps", "qoe_sessionId": null, "type_event": null};;;;;N/A;17059165;;10.241.164.84;IPv4;29;HD;;;;;;;;;WIFI;DTV;IPTV;2255508521;0;4D535443;BA-ICS42-GPON;CEICS02;SCSJS01;RCSJS01;;;;;;0;0;0;0;0;0;0;0;3.0.11;1280x720@60p;N/A;2020.06.26.00.08.27;5263162195;LiveTV;N/A;;;1;ALL;VIP4242W;239.130.1.0:22220;0;0;;;EBVS;;

在这种情况下是 30 和 31,但我找不到如何更新文件中的这对字段。有什么建议吗?

【问题讨论】:

  • edit 你的问题显示一个minimal reproducible example 来证明你的问题。带有滚动条的大量行列表并没有为我们提供任何我们可以轻松理解和复制/粘贴以进行测试的内容 - 使用 3 或 4 行每行 4 或 5 个字段的示例应该足够了。

标签: linux unix awk sed


【解决方案1】:

您不能直接编辑 bz2 压缩文件,我能想到的实现您要求的唯一方法是:

bzcat OBACountryIPTV_CALICUX_Report_Session_Local_Timezone_2021-07-02_000000.csv.bz2 | awk 'BEGIN{FS=OFS=";"}{$30=gensub(/^..(..)\/(..)\/(..)(.*)$/, "\\3/\\2/\\1\\4","1",$30);$31=gensub(/^..(..)\/(..)\/(..)(.*)$/, "\\3/\\2/\\1\\4","1",$31);print }' | bzip2 > OBACountryIPTV_CALICUX_Report_Session_Local_Timezone_2021-07-02_000000.csv.bz2.tmp
mv OBACountryIPTV_OBACountryIPTV_CALICUX_Report_Session_Local_Timezone_2021-07-02_000000.csv.bz2.tmp CALICUX_Report_Session_Local_Timezone_2021-07-02_000000.csv.bz2  #if the size looks right and you verified the content has changed as expected.

我确信使用 awk 进行重新排列有更简单/更有效的方法;另请注意,gensubGNU awk 扩展,不符合 POSIX。

awk部分的解释:

BEGIN{FS=OFS=";"} - 告诉 awk ; 是一个字段分隔符。

$30=gensub(/^..(..)\/(..)\/(..)(.*)$/, "\\3/\\2/\\1\\4","1",$30) - 解析第 30 个字段(不需要的日期格式字段中的第一个),^.. 匹配年份的世纪部分,(..) 捕获年份和十年,随后的捕获月份和天,分别。 (.*) 然后捕捉时间。 "\\3/\\2/\\1\\4" 使用捕获的组重建时间和日期(它们按照捕获的顺序编号,因此\\1 匹配年份的最后两位数字)并将值重新分配给第 30 个字段。

然后我们对第 31 个字段重复相同的过程。

【讨论】:

  • 优秀!!!非常感谢 Tink,效果很好。如果您向我解释您使用的正则表达式和命令,那就太过分了?我想知道它是如何工作的!
  • 很高兴它奏效了,完全没有,我将编辑答案。
  • P.S.: fue un placer ayudarte ;)
  • Excelente 西班牙语 Tink,agradecido 总!!
猜你喜欢
  • 1970-01-01
  • 2016-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-15
相关资源
最近更新 更多