我试图通过提取列并将其粘贴到新文件中来从一个大文件中准备数据文件。
给定数据的列数非常大。我想通过分割数据来准备多个数据文件。
我正在尝试下面的脚本,但它不起作用。我预计该错误是由于指定要复制的列范围造成的。
#!/bin/bash
paste <(awk '{print $1,$2,$3,...$19,$20}' Precipitation.csv ) > aaaaa1
paste <(awk '{print $21,$22,$23,...$39,$40}' Precipitation.csv ) > aaaaa2
paste <(awk '{print $41,$42,$43,...$99,$100}' Precipitation.csv ) > aaaaa3
您能帮我改正代码吗?
答案1
这看起来像是一个案例cut
会比以下做得更好awk
:
cut -d , -f1-20 Precipitation.csv > aaa1
cut -d , -f21-40 Precipitation.csv > aaa2
cut -d , -f41-100 Precipitation.csv > aaa3
-d ,
指定分隔符(逗号,因为输入称为 CSV,但您可以更改它)。通过包含-f N-M
挑选出要出现在输出中的字段。如果任何字段中嵌入了逗号,它就会被破坏——在这种情况下,您可能需要一个真正的 CSV 解析器,尽管如果确实不可能的话,也可以将某些东西组合在一起。N
M
输出将使用与输入相同的分隔符。 GNUcut
支持--output-delimiter=STRING
设置不同分隔符的选项,但我认为其他人不会这样做。 FreeBSDcut
包括-w
按空格分割选项更接近awk
默认情况。如果您希望在其他地方实现这些行为之一,那么在之前/之后转换分隔符可能是您最好的选择。
答案2
后续行动迈克尔·霍默的回答:
ksh
为了避免使用支持进程替换( , zsh
, )的 shell 多次读取文件bash
:
tee < Precipitation.csv >(cut -d, -f1-20 > aaa1) >(cut -d, -f21-40 > aaa2) |
cut -d, -f41- > aaa3
答案3
和perl
:
perl -F',' -anle 'print join ",", @F[0..19]' Precipitation.csv > aaa1
perl -F',' -anle 'print join ",", @F[20..39]' Precipitation.csv > aaa2
perl -F',' -anle 'print join ",", @F[40..99]' Precipitation.csv > aaa3
答案4
这提供了更好的性能,因为我们只读取输入文件一次
awk '{out1=$1; for(i=2; i<=20; i++) {out1 = (out1 FS $i)}
out2=$21; for(i=22; i<=40; i++) {out2=(out2 FS $i)}
out3=$41; for(i=42; i<=100; i++) {out3=(out3 FS $i)}
print out1 > "aaaaa1"; print out2 > "aaaaa2"; print out3 > "aaaaa3"}' Precipitation.csv
或者您可以在以下命令中键入所有字段编号。将“...”替换为所有必填字段编号
awk '{print $1,$2,$3,...$19,$20 > "aaaaa1";
print $21,$22,$23,...$39,$40 > "aaaaa2";
print $41,$42,$43,...$99,$100 > "aaaaa3"}' Precipitation.csv