我有一个包含500列的文件,我需要将每列拆分为一个新文件,同时在所有文件中打印$1作为公共文件。下面是一个示例文件,我使用下面的bash/awk解决方案做到了这一点:
ID F1 F2 F4 F4
aa 1 2 3 4
bb 1 2 3 4
cc 1 2 3 4
dd 1 2 3 4
num=('1' '2' '3' '4')
for i in ${num[@]}; do awk -F "t" -v col="$i" '{print $1,$col}' OFS="t"
Input.txt > ${i}.txt; done
它给出了所需的输出:
1.txt
ID ID
aa aa
bb bb
cc cc
dd dd
2.txt
ID F1
aa 1
bb 1
cc 1
dd 1
....
但是,我无法跟踪哪个文件对应于哪一列,因为输出文件名是字段号,而不是字段名。是否可以将字段的头作为输出文件名的前缀?
ID.txt
ID ID
aa aa
bb bb
cc cc
dd dd
F1.txt
ID F1
aa 1
bb 1
cc 1
dd 1
您可以在一个awk
脚本中完成所有操作。处理第一行时,将所有列标题放在一个数组中。然后,当您处理行时,您将在循环中写入该数组中的文件名。
awk -F't' 'NR == 1 { split($0, filenames) }
{for (col = 1; col <= NF; col++) {
file= filenames[col] ".txt";
print $1, $col >> file;
close(file) } }' Input.txt
如果我正确理解您的需求,那么您似乎非常接近。尝试
num=('1' '2' '3' '4')
for i in ${num[@]}; do
echo "i=$i"
awk -F "t" -v col="$i" -v OFS="t" '
NR==1{fName=$(col+1)".out";next}
{print $1,$(col+1) > fName}' data.txt
done
1>cat F1.out
aa 1
bb 1
cc 1
dd 1
. . . .
1>cat F4.out
aa 4
bb 4
cc 4
dd 4
编辑
如果您需要保留示例输出中所示的标题,只需删除;next
即可。
编辑2
若有多个具有相同名称的列,则可以使用>> fName
将数据附加到同一文件中。用这种技术警告一句话。使用> fName
时,每次重新运行脚本时都会"重新启动"文件。但是,当使用>>
时,每次运行脚本时都会将其附加到每个文件中。这可能会给下游流程带来问题;-)。。。因此,您需要添加一些代码来清理之前运行的脚本。
这里,我们依赖于这样一个事实,即awk
也可以使用> fName
将输出写入文件(其中fName
被定义为col(Num)+1的值(跳过第一列的值)。
而且,如果你每天要这样做数千次,那么让awk
读取一次文件并从内部循环创建所有输出,就值得进一步优化上面的每条注释。但是,如果您只需要做几次,那么您的"使用unix/linux工具将任务分解为可管理的部分"是非常合适的。
IHTH