我有一个超过 20.000 行的文本文件,如下所示:
7 128550681 128550681 Intron:1:36:RETAINED-RETAINED;Transcript:NM_001135914.1;Gene:KCP:protein_coding 1 1 0 0
1 17718672 17718672 Intron:9:16:RETAINED-RETAINED;Transcript:NM_207421.4;Gene:PADI6:protein_coding 1 1 0 0
1 17718672 17718672 Intron:9:16:RETAINED-RETAINED;Transcript:NM_207421.4;Gene:PADI6:protein_coding 1 1 0 0
4 86035 86035 Exon:4:5:RETAINED;Transcript:NM_001286052.1;Gene:ZNF595:protein_coding 1 1 0 0
3 12942851 12942851 Intron:14:14:SKIPPED-ALTTENATIVE_3SS;Transcript:NM_001134382.2;Gene:IQSEC1:protein_coding 1 1 0 0
我需要的是第四列只包含 Gene:genename,所以输出如下:
7 128550681 128550681 Gene:KCP 1 1 0 0
1 17718672 17718672 Gene:PADI6 1 1 0 0
1 17718672 17718672 Gene:PADI6 1 1 0 0
4 86035 86035 Gene:ZNF595 1 1 0 0
3 12942851 12942851 Gene:IQSEC1 1 1 0 0
Gene:genename
*当尝试按:
或分割时,问题并不总是出现在同一位置;
我知道非常基本的 awk/sed,例如如何选择特定列、如何 grep 包含某些模式的行
答案1
我能够使用以下awk
命令来完成此操作:
awk '{sub(/^.*;/,"",$4); print}' input
这将删除第 4 列中的所有内容,直到最后一个;
,这可能对您不起作用(请参阅 Steeldriver 的评论)。在这种情况下,请更新您的问题并进行澄清。
答案2
awk
仅与 POSIX 定义的结构一起使用,
awk 'match($4, /Gene:(.+)\:/){ $4=substr($4, RSTART, RLENGTH-1) }1' file
为了使输出更加整齐地对齐,请将输出通过管道传输到| column -t
将制表符分隔的列。如果您不确定 的位置Gene:genename
,请更改 来awk
查找该行中任意位置的模式,并使用所需的值修改第四列。更改为$4
($0
整行)应该可以正常工作。
awk 'match($0, /Gene:(.+)\:/){ $4=substr($0, RSTART, RLENGTH-1) }1' file
答案3
perl -pale 's#(?:\H+\h+){3}\K\H+#($F[3] =~ /(?:^|;)(Gene:[^:]+)/)[0]#e' input-file.txt
° 如果第四个字段中的基因位置不固定,则可以按上述方法操作。
° 我们通过正则表达式将第四个字段归零(?:\H+\h+){3}\K\H+
,并立即将其替换为命令替换部分中使用的另一个正则表达式s///e
。
答案4
珀尔:
perl -F'\h+' -lane '
for ( $F[3] ) {
my $a = index(";$_", ";Gene:" );
my $b = index(";$_", ":", $a+6 );
$_ = substr(";$_", $a+1, $b-$a-1);
}
print join "\t", @F;
' input-file.txt
输出:
7 128550681 128550681 Gene:KCP 1 1 0 0
1 17718672 17718672 Gene:PADI6 1 1 0 0
1 17718672 17718672 Gene:PADI6 1 1 0 0
4 86035 86035 Gene:ZNF595 1 1 0 0
3 12942851 12942851 Gene:IQSEC1 1 1 0 0
$ 128550681 128550681 Gene:$$$ 1 1 0 0
解释:
perl
选项:-n
=> 调用输入的逐行读取。-F
=> 将使FS = horizontal whitespace
.-a
=> 将每一行拆分为字段(基于-F
选项设置的 FS 或默认情况下的单个空格)并将它们存储在 array 中@F
。-l
=> 将使RS = ORS = "\n"
.-e
=> 接下来的内容将被视为Perl
代码并应用于每一行,即记录。
data structures
涉及:@F
=> 用拆分记录获得的字段填充的数组。从 0 开始索引。$F[3]
记录中的第四个字段也是如此。$a
;Gene:
=> 保存子字符串在第四个字段中的位置。$b
=> 保存子字符串在第 4 个字段中的位置:
,可以在 的位置之后查找 6 位数字;Gene:
。 IOW,它找到了:
后的第二个;Gene
。注意:我们在搜索字符串中填充一个分号,即 ,$F[3]
因为 的位置Gene:
可以是任何地方,所以它也可以位于第四个字段的开头。这是为了应对这种可能性。$_
$F[3]
=> 保存循环内部的本地化版本for
。内置substr
函数将提取gene:...
信息并将其存储回$F[3]
.- 注意:
my
变量定义之前的限定符将$a,$b
它们标记为词法变量,其范围仅限于循环for
。 - 注意:循环
$_
内部for
并不引用当前记录/行。它已被重载并本地化,循环持续时间for
为$F[3]
。
GNU Sed:
sed -Ee '
s/\S+/\n&\n/4
s/\n(.*;)?(Gene:[^:]+):.*\n/\2/
' input-file.txt
解释:
- 我们用换行符标记第四个字段。
- 在当前行中放样区域后,我们然后找出所需的数据(在我们的例子中),
Gene:
然后,as many non colons we meet on the way before we hit the next colon
. - 该方法不会干扰各个字段之间存在的间距。这可能重要也可能不重要。
- 注:仅供参考:假设第四个字段中有一个基因。对于多个基因,它不会出错或发出警告,而是默默地选择该记录的第四个字段的最后一个基因。