每行中列数不一致的文件所需的转置类型

时间:2011-06-17 15:02:05

标签: bash shell unix

我有一个制表符分隔文件(每行中的列数不固定),如下所示:

chr1 92536437 92537640 NM_024813 NM_053274

我希望按照以下顺序从中获取一个文件(前三列是分割时需要的标识符)

chr1 92536437 92537640 NM_024813
chr1 92536437 92537640 NM_053274

有关shell脚本的建议。

4 个答案:

答案 0 :(得分:4)

#!/bin/bash
{
    IFS='   '
    while read a b c rest
    do
        for fld in $rest
        do
            echo -e "$a\t$b\t$c\t$fld"
        done
    done
}

请注意,您应该在那里输入一个真实标签(IFS

我还以为我应该做一个perl版本:

#!/bin/perl -n
($a,$b,$c,@r)=(chomp and split /\t/); print "$a\t$b\t$c\t$_\n" for @r

从命令行执行所有操作,从in.txt读取并输出到out.txt:

perl -ne '($a,$b,$c,@r)=(chomp and split /\t/); print "$a\t$b\t$c\t$_\n" for @r' in.txt > out.txt

当然如果你保存perl脚本(比如script.pl)

perl script.pl in.txt > out.txt

如果您还使脚本文件可执行(chmod +x script.pl):

./script.pl in.txt > out.txt

HTH

答案 1 :(得分:3)

不是shell,另一个答案非常好,但我在perl中使用了它:

perl -F'/\s/' -lane '$,="\t"; print @F,$_ for splice @F,3' $FILE

修改:新版(更难以理解;)版本,受其他答案的启发。滥用perl的命令行参数和特殊变量进行自动分割和行结束处理。

意味着:对于前三个(for splice @F,3)之后的每个字段,打印前三个字段(print @F,$_)。

-F将字段分隔符设置为\s(应为\t-a自动分割为@F

-l启用-n的行结束处理,为每行输入运行-e代码。

$,是输出字段分隔符。

答案 2 :(得分:1)

[被修改]

所以你想复制每个剩余项目的前三列吗?

$ cat File | while read X
      do PRE=$(echo "$X" | cut -f1-3 -d ' ')
      for Y in $(echo "$X" | cut -f4- -d ' ')
          do echo $PRE $Y >> OutputFilename
      done
  done

返回:

chr 786 789 NM
chr 786 789 NR
chr 786 789 NT
chr 123 345 NR

这会将前三个以空格分隔的列作为前缀切割,然后滥用for循环将逐步通过空格分隔列表来调用echo的事实。

享受。

答案 3 :(得分:0)

这只是您data comparison in two files问题的一部分。

从那里提取我稍微讨厌的解决方案:

for i in 4 5 6 7; do join -e _ -j $i f f -o 1.1,1.2,1.3,0; done | sed '/_$/d'