在 Bash 脚本中从 csv 中选择特定日期的行

在 Bash 脚本中从 csv 中选择特定日期的行

我有一个名为的 CSV 文件,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 

我只想选择那些日期为星期日的行,日期格式如下YYYYMMDD HH:MM:SS

答案1

鉴于

$ 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

答案2

此行代码可以给出预期的结果,并可以通过管道使用进行扩展:

$ 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;) 类似于沃尔蒂纳托的但是,我没有在循环内进行过滤,而是连接了星期几并允许进一步处理:

$ 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

答案3

阅读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

删除最后一个2>/dev/null即可查看调试输出。

答案4

使用 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

参考:

相关内容