【问题标题】:Bash - issue with deleting rows containing null valuesBash - 删除包含空值的行的问题
【发布时间】:2020-02-01 15:00:21
【问题描述】:

我有一个 .csv 文件,需要按以下方式修改:对于文件中的每一列,检查该列是否包含任何空条目。如果是这样,它将从文件中删除。否则,该列将保留。我尝试使用以下脚本解决此问题:

cp file-original.csv file-tmp.csv

for (( i=1;i<=65;i++)); do
  for var in $(cut -d, -f$i file-tmp.csv); do
    if [ -n $var ]; then
      continue
    else
      cut -d, --complement -f$i file-tmp.csv > file-tmp.csv
      break
    fi
  done
done

我假设问题在于将每次迭代的结果保存到一个也正在迭代的文件中 (file-tmp.csv)。但是,我不确定如何规避这一点。

【问题讨论】:

  • 你必须使用一个临时文件,例如here。我将添加一个替代您的方法的答案,该方法首先避免复制。
  • Bash FAQ 001。但是,对于允许引用字段的 CSV 文件,您应该使用具有适当 CSV 解析库的通用语言。

标签: bash


【解决方案1】:

你必须使用临时文件

cut -d, --complement -f$i file-tmp.csv > tmp.csv && mv tmp.csv file-tmp.csv

for var in $(cut -d, -f$i file-tmp.csv) 有问题:您将无法检测到这样的空行,因为分词只会跳过它。

您可以通过跟踪要删除的列来避免所有文件副本,然后一次性删除它们:

for i in {1..65}; do
    if grep -q '^$' <(cut -d, -f "$i" file-original.csv); then
        drop+=("$i")
    fi
done

cut -d, --complement -f "$(IFS=,; echo "${drop[*]}")" file-original.csv \
    > file-tmp.csv

这使用 grep 来查看一列是否包含空行,避免了慢循环和分词错误。

在 for 循环之后,drop 数组包含我们要删除的所有列号,$(IFS=,; echo "${drop[*]}") 将它们打印为逗号分隔列表。

【讨论】:

    【解决方案2】:
    $ cat foo.csv
    a,,c,d
    a,b,,d
    
    $ cat tst.awk
    BEGIN { FS=OFS="," }
    NR==FNR {
        for (inFldNr=1; inFldNr<=NF; inFldNr++) {
            if ($inFldNr ~ /^$/) {
                skip[inFldNr]
            }
        }
        next
    }
    FNR==1 {
        for (inFldNr=1; inFldNr<=NF; inFldNr++) {
            if ( !(inFldNr in skip) ) {
                out2in[++numOutFlds] = inFldNr
            }
        }
    }
    {
        for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
            inFldNr = out2in[outFldNr]
            printf "%s%s", $inFldNr, (outFldNr<numOutFlds ? OFS : ORS)
        }
    }
    
    $ awk -f tst.awk foo.csv foo.csv
    a,d
    a,d
    

    【讨论】:

      【解决方案3】:

      查看您的问题,我找到了一个非常简单的答案,仅使用grep 命令并输出到临时文件。 假设您的 CSV 文件名为 test.csv。下面创建了一个文件test1.csv,它消除了所有包含null值的行:

      grep -v null test.csv > test1.csv
      

      -v 选项反转grep 命令的输出,回显其中不包含null 的行。输出可以转发到另一个文件,然后你可以替换原来的test.csv文件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-03
        • 1970-01-01
        • 1970-01-01
        • 2022-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多