我有一个看起来像这样的文件:
chrom start stop strand isoform mu_codon mut_codon2 more_info
chr22 43089055 43089055 - NM_017436 C 300 903delC
chr22 43089715 43089717 - NM_017436 CTT 79 241_243delTTC
chr12 53701873 53701875 - NM_015665 TTC A 1292_1294delTTCinsA
如果第七列中的值包含数字而不是字母,我想用空格替换它们。
例如,这是我想要的输出:
chrom start stop strand isoform mu_codon mut_codon2 more_info
chr22 43089055 43089055 - NM_017436 C 903delC
chr22 43089715 43089717 - NM_017436 CTT 241_243delTTC
chr12 53701873 53701875 - NM_015665 TTC A 1292_1294delTTCinsA
我需要保留文件中的空间,这样我的列就不会被更改。关于如何做到这一点有什么想法吗?或许awk
?我仍在学习这些技术。你能解释一下你的答案吗?
答案1
例如,当您想保留列时,您可以将输出字段分隔符更改为非分隔tab
符space
,如果您依赖列计数,则进一步处理会更容易。所以你可以使用以下awk
:
awk 'BEGIN { OFS = "\t"; }; { if ($7 ~ "^[0-9]*$") $7 = " "; else $7 = $7; }; 1'
在BEGIN
本节中,我们将输出字段分隔符(OFS
)更改为tab
。在下一节中,我们检查 7 th是否仅包含数字,如果是,我们将值更改为space
,如果不保留该值。但$7 = $7
我们确信我们会因为更改而重建当前行(记录)OFS
。如果字段分隔符( ) 设置为 ,则更改OFS
可确保进一步处理该输出将包含 8 列。awk
FS
tab
答案2
sed -e's/ *[^ 0-9]*/&\n/6;:n' \
-e's/\(\n[^ ]*\)[^ ]/\1 /;tn' \
-e's/\n//' <infile
这里有一些sed
可以做到的。我们要做的第一件事是将第 6 次出现的一个或多个空格替换为零个或多个[^ 0-9]
非空格或数字字符的序列,其自身后跟换行符。
基本上,这意味着如果第七列完全由空格或数字以外的字符组成,sed
则将在其后面附加一个换行符,否则sed
将在其前面附加一个换行符。
在下一条语句中,我们将模式空间中紧跟在换行符后面的所有非空格字符替换为空格字符。当然,只有当换行符后面还没有空格字符时才会发生这种情况,如果第七列不是数字,就会发生这种情况。
最后,我们删除插入的换行符。
输出
chrom start stop strand isoform mu_codon mut_codon more_info
chr22 43089055 43089055 - NM_017436 C 903delC
chr22 43089715 43089717 - NM_017436 CTT 241_243delTTC
chr12 53701873 53701875 - NM_015665 TTC A 1292_1294delTTCinsA
答案3
awk '{gsub("^[0-9]*$"," ",$7);$7=$7;OFS="\t";print}' file.txt
答案4
Perl 来拯救:
#!/usr/bin/perl
use warnings;
use strict;
while (<>) { # Process line by line.
my @F = split /(\s+)/; # Split the line into @F, keep whitespace as members, too.
$F[12] =~ s/./ /g # Replace any character with space
if $F[12] =~ /^[0-9]+$/; # if there are just digits.
print @F; # Print the result.
}