具有以下内容的文件:
1111,2222,3333,4444
aaaa,bbbb,cccc,dddd
我寻求获得一个与原始文件相同但缺少第 n 列的文件,例如 n = 2 (或者可能是 3)
1111,2222,4444
aaaa,bbbb,dddd
或者,对于 n = 0(或者可以是 1)
2222,3333,4444
bbbb,cccc,dddd
真实的文件可能有千兆字节长,有数万列。
与往常一样,在这种情况下,我怀疑命令行魔术师可以提供一个优雅的解决方案......:-)
在我的实际案例中,我需要删除 2 个第一列,这可以通过按顺序删除第一列两次来完成,但我认为概括一下会更有趣。
答案1
我相信这是 GNU coreutils 特有的:
$ cut --complement -f 3 -d, inputfile
1111,2222,4444
aaaa,bbbb,dddd
通常,您可以通过 -f 指定所需的字段,但通过添加 --complement ,您自然可以颠倒含义。来自“人切”:
--complement
complement the set of selected bytes, characters or fields
需要注意的是:如果任何列包含逗号,则会抛出 cut off,因为 cut 不是与电子表格相同的 CSV 解析器。许多解析器对于如何处理 CSV 中的转义逗号有不同的想法。对于简单的 CSV 情况,在命令行上,cut 仍然是可行的方法。
答案2
如果数据只是由逗号分隔的列组成:
cut -d , -f 1-2,4-
您也可以使用 awk,但这有点尴尬,因为虽然清除字段很容易,但删除分隔符需要一些工作。如果你没有空字段,那也不算太糟糕:
awk -F , 'BEGIN {OFS=FS} {$3=""; sub(",,", ","); print}'
如果您有实际的 CSV,如果正确引用,逗号可以出现在字段内,那么您需要真正的 CSV 库。
答案3
使用 CSV 感知工具从无标题 CSV 输入文件中删除前两列:
$ cat file
1111,2222,3333,4444
aaaa,bbbb,cccc,dddd
$ mlr --csv -N cut -x -f 1,2 file
3333,4444
cccc,dddd
-x
操作选项cut
在磨坊主( mlr
) 导致操作排除命名字段(在本例中为字段号 1 和 2)。如果 CSV 数据有标题,我们就可以使用命名字段-f
(-N
在这种情况下也需要删除该选项)。
由于 Miller 支持 CSV,因此它可以处理包含嵌入逗号、引号和换行符的正确引用字段。
答案4
尝试使用以下命令删除使用索引的列。
dropColumnCSV --index=0 --file=file.csv
如果列用逗号分隔,这将起作用,如下所示sed函数内部使用命令来删除字符串。
dropColumnCSV() {
# argument check
while [ $# -gt 0 ]; do
case "$1" in
--index=*)
index="${1#*=}"
;;
--file=*)
file="${1#*=}"
;;
*)
printf "* Error: Invalid argument. *\n"
return
esac
shift
done
# file check
if [ ! -f $file ]; then
printf "* Error: $file not found.*\n"
return
fi
# sed remove command index zero
if [[ $index == 0 ]]; then
sed -i 's/\([^,]*\),\(.*\)/\2/' $file
# sed remove command index greater than zero
elif [[ $index > 0 ]]; then
pos_str=$(for i in {1..$(seq "$index")}; do echo -n '[^,]*',; done| sed 's/,$//') ;
sed -i 's/^\('$pos_str'\),[^,]*/\1/' $file
fi
}