我有一个CSV文件,其中行的理想格式为:
taxID#,科学名称,王国, k ,门, p ,班级, c ,订单, o ,家庭, f ,genus, g
......其中王国,门等是标识符,文字("王国",..."门"),以及标识符后面的值(k, p等,是那些王国,门等的实际值。
示例:
240395,Rugosa emeljanovi,kingdom,Metazoa,phylum,Chordata,class,Amphibia,order,Anura,family,Ranidae,genus,Rugosa
但是,并非所有行都具有所有级别的分类,即任何一行都可能缺少标识符/值对的列,例如," class,c,&#34 ;并且任何2列PAIR都可以独立于其他对缺失而丢失。此外,如果字段丢失,它们的标识符字段将永远丢失,所以我永远不会得到王国,门和#34;没有" k "的价值。它们之间。因此,很多我的文件缺少随机字段:
...
135487,Nocardia cyriacigeorgica,class,Actinobacteria,order,Corynebacteriales,genus,Nocardia
10090,Mus musculus,kingdom,Metazoa,phylum,Chordata,class,Mammalia,order,Rodentia,family,Muridae,genus,Mus
152507,uncultured actinobacterium,phylum,Actinobacteria,class,Actinobacteria
171953,uncultured Acidobacteria bacterium,phylum,Acidobacteria
77133,uncultured bacterium
...
问题:如何编写一个可以" pad"的bash shell脚本?文件中的每一行,以便插入可能从我的理想格式中丢失的每个字段对,并且其后面的值列只是空白。 期望的输出:
...
135487,Nocardia cyriacigeorgica,kingdom,,phylum,,class,Actinobacteria,order,Corynebacteriales,family,,genus,Nocardia
10090,Mus musculus,kingdom,Metazoa,phylum,Chordata,class,Mammalia,order,Rodentia,family,Muridae,genus,Mus
152507,uncultured actinobacterium,kingdom,,phylum,Actinobacteria,class,Actinobacteria,order,,family,,genus,
171953,uncultured Acidobacteria bacterium,phylum,Acidobacteria,clas,,order,,family,,genus,
77133,uncultured bacterium,kingdom,,phylum,,class,,order,,family,,genus,
...
备注:
我尝试过的事情:
我写了一个简单的if / then脚本,它按顺序检查预期字段是否消失。伪代码:
如果" $ f3"不是"王国",垫
但问题是,如果王国真的失踪了,它会在输出中填补,但其余的场变量会被淹没,我不能只是这样说
如果" $ f5"不是"门",垫
因为如果王国失踪,门可能现在在第3场($ f3),而不是$ f5,也就是说,如果它也没有丢失。 (我通过将字符串变量连接到基于每个字段缺失的预期输出,并且如果字段没有丢失则简单地连接原始值,然后将完成的,假定填充的行回显到输出)来实现这一点。
我希望能够像这样执行我的脚本
bash pad.sh prePadding.csv postPadding.csv
但如果需要,我会接受使用Mac Excel 2011的答案。
谢谢!
答案 0 :(得分:1)
这将是bash使用关联数组的答案:
#!/bin/bash
declare -A THIS
while IFS=, read -a LINE; do
# we always get the #ID and name
if (( ${#LINE[@]} < 2 || ${#LINE[@]} % 2 )); then
echo Invalid CSV line: "${LINE[@]}" >&2
continue
fi
echo -n "${LINE[0]},${LINE[1]},"
THIS=()
for (( INDEX=2; INDEX < ${#LINE[@]}; INDEX+=2 )); do
THIS[${LINE[INDEX]}]=${LINE[INDEX+1]}
done
for KEY in kingdom phylum class order family; do
echo -n $KEY,${THIS[$KEY]},
done
echo genus,${THIS[genus]}
done <$1 >$2
它还验证CSV行,使它们包含至少2列(ID和名称),并且它们具有偶数列。
可以扩展脚本以进行更多的错误检查(例如,如果两个参数都被传递,如果输入存在,等等),但它应该按照您发布的方式按预期工作。