![如何根据两个条件使用 bash 过滤 csv 文件中的行?](https://linux22.com/image/941564/%E5%A6%82%E4%BD%95%E6%A0%B9%E6%8D%AE%E4%B8%A4%E4%B8%AA%E6%9D%A1%E4%BB%B6%E4%BD%BF%E7%94%A8%20bash%20%E8%BF%87%E6%BB%A4%20csv%20%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E8%A1%8C%EF%BC%9F.png)
我正在做一个项目,需要解析一个 csv 文件(印度肝病患者数据集) 并且我试图改变一列的位置。倒数第二列必须是最后一列。我正在遵循这些方法,但我不知道这是否是正确的方法:
while IFS="," read -r col1 col2 col9 col8 col
do
echo "$col1, $col2, $col9, $col8"
done < <(cut -d "," --fields=1,2,9,8 csvfile)
另外,我需要区分“男性”和“女性”(col2),并且只显示 col9 = 3 的值。期望的输出是:
Women
38,Female,3, 5.6
38,Female,3, 5.6
32,Female,3, 6
等等
Men
72,Male,3, 7.4
60,Male,3, 6.3
33,Male,3, 5.4
等等
如果不使用 grep 或 akw 我该如何做到这一点?
答案1
我同意 Muru 的观点,不允许使用最适合的工具并不是最佳选择,但可能有其目的。我认为不可能在一个循环中做到这一点,至少在不先对文件进行排序或删除标题的情况下不可能。使用关联数组,可以模拟“分组依据”,其中键变为 Female 或 Male,其字段被“序列化”为值。在第一个环形 _
用于跳过字段,第二个用于环形迭代所有键并格式化输出。
#!/bin/bash
declare -A A=()
declare -A B=([Male]=Men [Female]=Women)
while IFS=, read -r a b _ _ _ _ _ c d _ ; do
[[ $d = 3 ]] && \
A[$b]+=" $a $b $d $c"
done < file.csv
for e in ${!A[@]}; do
printf %s%s\\n "$nl" ${B[$e]}
printf '%s, %s, %s, %s\n' ${A[$e]}; nl=$'\n'
done
答案2
我会在 echo 周围粘贴一个 IF 语句并将其附加到单独的文件中。
在读取循环开始之前
# quietly erase CSV files
rm col2eq8.csv 2> /dev/null
rm col2noteq8.csv 2> /dev/null
在你的读取循环中:
# if $col2 equals 8
if [[ "$col2" -eq 8 ]]
then
# then re-order columns and append to col2eq8.csv file
echo "$col1, $col2, $col9, $col8" >> col2eq8.csv
else
# else re-order columns and append to col2noteq8.csv
echo "$col1, $col2, $col9, $col8" >> col2noteq8.csv
fi
更改两个 echo 命令以按照您想要的顺序获取您想要的字段。
如果需要根据列进行分隔,请将“$col2 -eq 8”更改为您想要的任何条件。
有关其他仅限 bash 的 CSV 操作,请参阅Bash CSV 解析。