Linux/Bash按CSV日期条件筛选并追加写入目标文件
问题与解决方案建议
问题描述
我有三个CSV文件,格式如下:
Name,Price,Date,SKU
日期字段标准格式为yyyy-mm-dd,需要提取所有日期属于2020-01的记录,写入到data/2020/01/destinationFile.csv。要求首次运行时创建目标文件,后续运行仅追加符合条件的记录,不能覆盖原有数据。
我当前使用的命令是:
awk -F, '$3 ~ /2020-01/ {print}' sourceFile.csv > data/2020/01/destinationFile.csv
试过grep和awk,但不知道如何正确校验日期格式,比如过滤掉像2017这种不符合yyyy-mm-dd格式的无效日期记录。
源文件示例(sourceData.csv)
Name,Price,Date,SKU pixel 5, 20000, 2020-01-04, 124124 iphone 8, 35000,2019-12-11, 124125 note 20 , 50000, 2020-04-16, 124127 note 20 ultra, 60000, 2020-01-12, 124128 s 8, 15000, 2017, 124129
目标文件示例(destinationFile.csv)
pixel 5, 20000, 2020-01-04, 124124 note 20 ultra, 60000, 2020-01-12, 124126
解决方案
1. 解决追加覆盖问题
现有命令用>会直接覆盖目标文件,改用>>重定向符即可实现追加:
awk -F, '$3 ~ /2020-01/ {print}' sourceFile.csv >> data/2020/01/destinationFile.csv
2. 精准校验日期格式
要过滤掉无效日期,需要用正则匹配精确的yyyy-mm-dd格式,同时处理Date字段前后可能存在的空格:
awk -F, ' # 跳过表头行 NR == 1 { next } # 清理Date字段前后的空格 gsub(/^[ \t]+|[ \t]+$/, "", $3) # 匹配2020年1月的有效日期(01-31日) $3 ~ /^2020-01-(0[1-9]|[12][0-9]|3[01])$/ { print } ' sourceFile.csv >> data/2020/01/destinationFile.csv
gsub(/^[ \t]+|[ \t]+$/, "", $3):去除Date字段前后的空格,避免空格导致正则匹配失败/^2020-01-(0[1-9]|[12][0-9]|3[01])$/:精确匹配2020年1月的有效日期,排除2017、2020-01这类不符合格式的记录
3. 批量处理多个源文件
一次性处理三个CSV文件,同时跳过每个文件的表头:
awk -F, ' # 跳过每个源文件的第一行表头 NR == 1 && FNR == 1 { next } gsub(/^[ \t]+|[ \t]+$/, "", $3) $3 ~ /^2020-01-(0[1-9]|[12][0-9]|3[01])$/ { print } ' source1.csv source2.csv source3.csv >> data/2020/01/destinationFile.csv
4. 首次运行自动添加表头
如果需要目标文件包含表头,可先判断文件是否存在,不存在则写入表头:
# 检查目标文件是否存在,不存在则写入表头 if [ ! -f data/2020/01/destinationFile.csv ]; then echo "Name,Price,Date,SKU" > data/2020/01/destinationFile.csv fi # 追加符合条件的数据 awk -F, ' NR == 1 { next } gsub(/^[ \t]+|[ \t]+$/, "", $3) $3 ~ /^2020-01-(0[1-9]|[12][0-9]|3[01])$/ { print } ' sourceFile.csv >> data/2020/01/destinationFile.csv
内容的提问来源于stack exchange,提问作者James_B
相关产品推荐
相关产品推荐

