BSD sed无法替换所有“,0”

时间:2013-03-11 17:32:37

标签: bash csv sed

我对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脚本中?有没有更好的方法来完成这项任务?

3 个答案:

答案 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