如果数据文件如下所示:
snp200 snp1 snp100 snp32 1 1 0 2 0 0 0 2 2 2 2 1...
当 snp.. 完成并使用它们作为列名称,然后平均划分其余数字(每行中的总数字数应等于第一行中的列名称数)时,如何打破该行并将它们放在后续行作为每一行。在这个小例子中,有 4 个列名,因此其余 4 行应该有 4 位数字输出:
snp200 snp1 snp100 snp32
1 1 0 2
0 0 0 2
2 2 2 1
...
考虑到真实数据确实很大(超过32000个列名),任何建议
答案1
cat in.txt | perl -pe 's/(([^ ]+ +){4})/$1\n/g' > out.txt
正则表达式表示找到一个或多个非空格后跟一个或多个空格,并将前 2 个内容分组为 4 个一组,然后在每次匹配后添加一个新行。
测试用例:
echo "snp200 snp1 snp100 snp32 1 13454356 0 2 0 0 0 2 2 2 2 1" | perl -pe 's/(([^ ]+ +){4})/$1\n/g'
snp200 snp1 snp100 snp32
1 13454356 0 2
0 0 0 2
2 2 2 1
答案2
使用 BSD 的rs(1)
:
rs 0 4 <data.txt >out.txt
答案3
如果您需要的只是四列:
$ cat data.file | tr ' ' '\n' | columns -w 10 -c 4
snp200 snp1 snp100 snp32
1 1 0 2
0 0 0 2
2 2 2 1
答案4
如果命名标签的数量可能会有所不同,我们最好先计算它们。在 Perl 中,类似这样:
perl -lane '
$n++ while $F[$n] =~ /^[a-z]/;
do {
print join(" ", @F[$_*$n .. $_*$n + $n - 1])
} while (++$_*$n <= $#F)' < input
首先,$n
对以字母开头的每个字段进行增加,给出命名字段的数量,然后重复打印,用空格、字段连接0*$n
到1*$n - 1
、然后1*$n
到2*$n - 1
等等,只要$n
计数器小于表上的字段总数。线。这假设所有数据都在一行上,后续行将被视为单独的数据集。