我的数据文件如下所示:
chr1 762440 762981 SAMD11
chr1 858932 859148 KLHL17 SAMD11 NOC2L
chr1 859786 860145 KLHL17 SAMD11 NOC2L
chr1 890663 891747 KLHL17 NOC2L SAMD11 HES4
我希望将所有名称排在另一个之下,并使用前三列中的值。
像这样的东西
chr1 762440 762981 SAMD11
chr1 858932 859148 KLHL17
chr1 858932 859148 SAMD11
chr1 858932 859148 NOC2L
chr1 859786 860145 KLHL17
chr1 859786 860145 SAMD11
chr1 859786 860145 NOC2L
此输出用于前三行,但是整个集合都需要。
每行中的名称数量不固定,请记住这一点(可以是1或5或10或20个名称)
What I thought
使用sed -i .bak将名称一个放在另一个下面以及前三列中的值。
但最终它变得过于复杂。
你能想到一个更简单的解决方法吗?
谢谢
答案 0 :(得分:5)
使用awk
awk '{for (i=4;i<=NF;i++) print $1,$2,$3,$i}' file
chr1 762440 762981 SAMD11
chr1 858932 859148 KLHL17
chr1 858932 859148 SAMD11
chr1 858932 859148 NOC2L
chr1 859786 860145 KLHL17
chr1 859786 860145 SAMD11
chr1 859786 860145 NOC2L
chr1 890663 891747 KLHL17
chr1 890663 891747 NOC2L
chr1 890663 891747 SAMD11
chr1 890663 891747 HES4
答案 1 :(得分:3)
以下是我在Perl中的表现:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
while (<DATA>) {
chomp;
my @line = split;
for my $field (@line[3 .. $#line]) {
say "@line[0 .. 2] $field";
}
}
__END__
chr1 762440 762981 SAMD11
chr1 858932 859148 KLHL17 SAMD11 NOC2L
chr1 859786 860145 KLHL17 SAMD11 NOC2L
chr1 890663 891747 KLHL17 NOC2L SAMD11 HES4
答案 2 :(得分:2)
在bash中(100%内部命令) 我有这个答案:
#!/bin/bash
while read ONE TWO THREE FOUR
do
for ARG in $FOUR
do
if [ ${ARG:0:1} != "(" ] #<-- filtering out args with parentheses
then
echo "$ONE $TWO $THREE $ARG"
fi
done
done <"/path/to/your/datafile"
但是既然你改变了问题,这也会改变答案:
#!/bin/bash
while read ONE TWO THREE FOUR
do
for ARG in $FOUR
do
echo "$ONE $TWO $THREE $ARG"
done
done <"/path/to/your/datafile"
答案 3 :(得分:2)
怎么样:
while(<DATA>) {
chomp;
my @data = split" ",$_;
my $prefix = join" ",@data[0..2];
for(3 .. $#data) {
next if $data[$_] =~ /\([-+]?\d+\)/;
say $prefix, " ", $data[$_];
}
}
__DATA__
chr1 762440 762981 SAMD11 (-98410)
chr1 858932 859148 KLHL17 (-36927), SAMD11 (-2081), NOC2L (+35639)
chr1 859786 860145 KLHL17 (-36001), SAMD11 (-1155), NOC2L (+34713)
<强>输出:强>
chr1 762440 762981 SAMD11
chr1 858932 859148 KLHL17
chr1 858932 859148 SAMD11
chr1 858932 859148 NOC2L
chr1 859786 860145 KLHL17
chr1 859786 860145 SAMD11
chr1 859786 860145 NOC2L
答案 4 :(得分:2)
因为你也有Python标签,所以我在Python中这样做(从命令行的stdin或文件读取输入,并将输出写入stdout)。
#!/usr/bin/python
import fileinput
for line in fileinput.input():
parts = line.strip().split()
first_three = " ".join(parts[:3])
for code in parts[3:]:
print("{first_three} {code}".format(first_three=first_three, code=code))
答案 5 :(得分:2)
sed 's/^/\
/
t b
: b
s/\(\n\)\(\([^[:blank:][:cntrl:]]\{1,\}[[:blank:]]\{1,\}\)\{3\}\)\([^[:blank:][:cntrl:]]\{1,\}\)[[:blank:]]\{1,\}\([^[:blank:][:cntrl:]][^[:cntrl:]]*\)[[:blank:]]*$/\1\2\4\1\2\5/
t b
s/^\n//' YourFile
处理每一行,扩展任何最后一个参数。可以删除第一个t b
,但它会通过安全性重置测试
答案 6 :(得分:1)
这可能适合你(GNU sed):
sed -r 's/^((\S+\s+){3})(\S+)\s+(\S+)/\1\3\n\1\4/;P;D' file
答案 7 :(得分:0)
#!/usr/bin/perl
use warnings;
use strict;
请阅读您的文件:
my $infile = 'in.txt';
open my $input, '<', $infile or die "Can't open to $infile: $!";
拆分空格中的每一行(尽管如果您的数据以制表符分隔,我建议使用split(/\t/)
;
while (<$input>){
my @split = split(/\s+/);
print "$split[0]\t$split[1]\t$split[2]\t$split[3]\n";
}
输出:
chr1 762440 762981 SAMD11
chr1 858932 859148 KLHL17
chr1 859786 860145 KLHL17
chr1 890663 891747 KLHL17
chr1 896072 896354 NOC2L
chr1 954920 955343 HES4
chr1 1195296 1195488 PUSL1
chr1 1243975 1244505 UBE2J2
chr1 1284370 1284709 ACAP3
chr1 1373711 1374872 CCNL2