【问题标题】:BSD sed unable to replace all ",0,"BSD sed 无法替换所有“,0”
【发布时间】:2013-02-27 00:02:01
【问题描述】:

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

我有一个 csv 格式的大数据文件,用逗号分隔。就连文件的前两行也太大了这里就不贴了,大家可以找前两行here。

我需要将 0,8,9,-999,-999.0 的值替换为“NA”,因为这些值是缺失值的代码。

我在 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,0,,而您的输出包含,NA,0,?如果是这样 - 这是因为 ,0, 的每次替换只能在之前的 ,0, 替换结束的位置之后开始。
  • 确实!那么,0,0,怎么处理呢?
  • 如果除 0 以外的任何值都不能以 0 开头,则只需 ',0' => ',NA'
  • 您的代码将用 NA 替换 9990
  • @IvyLee:我手边没有 BSD 机器,所以无法测试任何建议。这就是为什么我发表评论而不是回答的原因。 (当然,您可以只使用 Perl:perl -ne 's/(^|(?<=,))([089]|-999(\.0)?)(?=,|$)/NA/g。无论如何,谁需要 sed?:-P)

标签: bash csv sed


【解决方案1】:

使用 sed,尝试:

sed -e 's/\-999\(\.0\)*/NA/g' -e :a -e 's/,[089],/,NA,/; ta' file

【讨论】:

    【解决方案2】:

    我认为 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 }。

    【讨论】:

      【解决方案3】:

      根据我的经验,在处理 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-08
        • 1970-01-01
        • 2014-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多