4

我对 GNU sed 和 BSD sed 之间的区别有所了解。不幸的是我没有linux机器,只有mac可用。

我有一个 csv 格式的大数据文件,用逗号分隔。即使文件的前两行太大,无法在此处发布,您可以在此处找到前两

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

4

3 回答 3

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
于 2013-03-11T18:27:08.747 回答
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 列表是否相等,如果发现为 true,则该字段被替换为NA,请注意 awk 在测试之前将该字段转换为数字。最后1调用默认块{ print $0 }

于 2013-03-11T18:33:37.090 回答
0

使用 sed,尝试:

sed -e 's/\-999\(\.0\)*/NA/g' -e :a -e 's/,[089],/,NA,/; ta' file
于 2013-03-11T21:30:24.137 回答