saaga Asked: 2020-01-07 08:25:47 +0800 CST2020-01-07 08:25:47 +0800 CST 2020-01-07 08:25:47 +0800 CST 在bash脚本中从csv中选择特定日期的行 772 我有一个test.csv包含这些值的 CSV 文件: A,table,20191229 16:41:58 B,table2,20191222 16:41:58 C,table3,20191223 16:40:58 D,table4,20191228 16:41:58 E,table5,20191227 16:41:58 F,table6,20191226 16:40:58 我只想选择星期几的那些行,日期是YYYYMMDD HH:MM:SS格式的。 scripts bash csv 4 个回答 Voted steeldriver 2020-01-07T08:51:13+08:002020-01-07T08:51:13+08:00 给定 $ cat test.csv A,table,20191229 16:41:58 B,table2,20191222 16:41:58 C,table3,20191223 16:40:58 D,table4,20191228 16:41:58 E,table5,20191227 16:41:58 F,table6,20191226 16:40:58 然后使用米勒 $ mlr --csvlite --implicit-csv-header --headerless-csv-output filter ' strftime(strptime($3,"%Y%m%d %H:%M:%S"), "%w") == "0" ' test.csv A,table,20191229 16:41:58 B,table2,20191222 16:41:58 Ictus 2020-05-01T09:41:52+08:002020-05-01T09:41:52+08:00 这个单线可以提供预期的结果以及通过管道使用扩展它的可能性: $ cat test.csv | (while read line; do day=$(date -d "$(echo $line|cut -d, -f3)" +%a); echo "$line,$day"; done;) | grep ',Sun$' | cut -d, -f1-3 A,table,20191229 16:41:58 B,table2,20191222 16:41:58 主要逻辑 (while read line; do day=$(date -d "$(echo $line|cut -d, -f3)" +%a); echo "$line,$day"; done;) 类似于waltinator 的,但是,我不是在循环内过滤,而是连接星期几并允许进一步处理: $ cat test.csv | (while read line; do day=$(date -d "$(echo $line|cut -d, -f3)" +%a); echo "$line,$day"; done;) A,table,20191229 16:41:58,Sun B,table2,20191222 16:41:58,Sun C,table3,20191223 16:40:58,Mon D,table4,20191228 16:41:58,Sat E,table5,20191227 16:41:58,Fri F,table6,20191226 16:40:58,Thu 现在,您可以使用grep过滤,如果需要grep ',Sun$',包括不同的日子grep -E ',(Sun|Sat)$': $ cat test.csv | (while read line; do day=$(date -d "$(echo $line|cut -d, -f3)" +%a); echo "$line,$day"; done;) | grep -E ',(Sun|Sat)$' A,table,20191229 16:41:58,Sun B,table2,20191222 16:41:58,Sun D,table4,20191228 16:41:58,Sat 最后, 然后只选择 3 个原始字段cut -d, -f1-3(在这里您也可以自由更改): $ cat test.csv | (while read line; do day=$(date -d "$(echo $line|cut -d, -f3)" +%a); echo "$line,$day"; done;) | grep -E ',(Sun|Sat)$' | cut -d, -f1-3 A,table,20191229 16:41:58 B,table2,20191222 16:41:58 D,table4,20191228 16:41:58 Best Answer waltinator 2020-01-07T08:44:18+08:002020-01-07T08:44:18+08:00 阅读man date,并执行以下操作: while read line ; do echo "line=$line">&2 din=$(echo "$line" | cut -d, -f3 | cut "-d " -f1) echo "din=$din">&2 dayofweek=$(date --date=$din +%a) echo "dow=$dayofweek">&2 if [[ "$dayofweek" = "Sun" ]] ; then echo "$line" fi done <test.csv 2>/dev/null 去掉final2>/dev/null就可以看到调试输出了。 user986805 2020-05-01T12:33:08+08:002020-05-01T12:33:08+08:00 使用 Sakamoto 的方法匹配多个工作日。 #!/bin/bash # 64 32 16 8 4 2 1 # 1 0 0 0 0 0 1 = 65 (Sat, Sun) # Sat ´ | | | | | | # Fri ---´ | | | | | # Thu ------´ | | | | # Wed ---------´ | | | # Tue ------------´ | | # Mon ---------------´ | # Sun ------------------´ a=(0 3 2 5 0 3 5 1 4 6 2 4) IFS=$'\n' for b in $(<test.csv); do ((c=10#${b:(-17):4})) # year ((d=10#${b:(-13):2})) # month ((e=10#${b:(-11):2})) # day (((1 << ((((c -= ((d < 3)))) + c / 4 - c / 100 + c / 400 + ${a[((d - 1))]} + e) % 7)) & 65)) && printf %s\\n "$b" done 参考: 星期几的确定 坂本算法的正确性
给定
然后使用米勒
这个单线可以提供预期的结果以及通过管道使用扩展它的可能性:
主要逻辑
(while read line; do day=$(date -d "$(echo $line|cut -d, -f3)" +%a); echo "$line,$day"; done;)
类似于waltinator 的,但是,我不是在循环内过滤,而是连接星期几并允许进一步处理:现在,您可以使用
grep
过滤,如果需要grep ',Sun$'
,包括不同的日子grep -E ',(Sun|Sat)$'
:最后,
然后只选择 3 个原始字段
cut -d, -f1-3
(在这里您也可以自由更改):阅读
man date
,并执行以下操作:去掉final
2>/dev/null
就可以看到调试输出了。使用 Sakamoto 的方法匹配多个工作日。
参考: