我对GNU sed和BSD sed之间的区别有所了解。不幸的是我没有linux机器,只有mac可用。
我有一个csv格式的大型数据文件,用逗号分隔。即使文件的前两行太大而无法在此处发布,您也可以找到前两行here。
我需要用“NA”替换0,8,9,-999,-999.0的值,因为这些值是缺失值的代码。
我在bash提示符中使用了以下sed命令
sed -e 's/\-999\.?\0?/NA/g' \
-e 's/\-999/NA/g' \
-e 's/,9,/,NA,/g' \
-e 's/,8,/,NA,/g' \
-e 's/,0,/,NA,/g' \
firsttwolines.csv
结果看起来很好,但仍然存在单个0
。怎么解决?以及如何将它放在bash脚本中?有没有更好的方法来完成这项任务?
答案 0 :(得分:1)
根据我的经验,在处理CSV文件格式时,像sed,awk这样的文本扫描工具很难处理所有的角落情况。我知道你在sed中特别要求解决方案,但它不能很好地完成工作。我推荐一种提供强大的CSV文件处理的语言,如Python或Tcl(还有更多,但这些是我所知道的)。这是Python的解决方案:
# csvreplace.py
import sys
import csv
if __name__ == '__main__':
infilename = sys.argv[1]
outfilename = sys.argv[2]
with open(infilename) as infile, open(outfilename, 'w') as outfile:
csvreader = csv.reader(infile)
csvwriter = csv.writer(outfile)
na_list = ['0', '8', '9', '-999', '-999.0']
for row in csvreader:
row = [col in na_list and 'NA' or col for col in row]
csvwriter.writerow(row)
您可以在bash脚本中将其用作:
python csvreplace.py data.csv out.csv
答案 1 :(得分:0)
我认为awk对于这项任务来说是更好的选择(用gawk和nawk测试过):
awk '{ for(i=1; i<=NF; i++) if($i == 0 || $i == 8 || $i == 9 || $i == -999) $i = "NA" } 1' FS=, OFS=, firsttwolines.csv
for循环遍历每个字段并测试它与NA列表的相等性,如果找到,则字段被NA
替换,请注意awk在测试之前将字段转换为数字。最后的1
调用默认块{ print $0 }
。
答案 2 :(得分:0)
使用sed,尝试:
sed -e 's/\-999\(\.0\)*/NA/g' -e :a -e 's/,[089],/,NA,/; ta' file