![计算特定连续字符及其出现位置和长度](https://linux22.com/image/117157/%E8%AE%A1%E7%AE%97%E7%89%B9%E5%AE%9A%E8%BF%9E%E7%BB%AD%E5%AD%97%E7%AC%A6%E5%8F%8A%E5%85%B6%E5%87%BA%E7%8E%B0%E4%BD%8D%E7%BD%AE%E5%92%8C%E9%95%BF%E5%BA%A6.png)
我有一个序列文件,想要计算连续字符“N”及其出现位置和长度假设我有一个名为mySequence.fasta
如下的文件:
>sequence-1
ATCGCTAGCATNNNNNNNNNNNNNNCTAGCATCATGCNNNNNNATACGCATCACANNNNNNNNNCgcatATCAC
预期输出应该是这样的:
Position 12 N 14
Position 38 N 6
Position 56 N 9
awk
请通过或sed
提供我的文件名帮助我解决此问题mySequence.fasta
答案1
您可以使用 来做到这一点awk
,它match()
设置RSTART
和RLENGTH
变量对此非常有用:
<mySequence.fasta awk -v C=N '{
i=0
while (match($0, C "+")) {
printf "Position %d %s %d\n", i+RSTART, C, RLENGTH
i += RSTART+RLENGTH-1
$0 = substr($0, RSTART+RLENGTH)
}}'
或者perl
使用@-
和@+
数组来记录匹配的开始和结束:
perl -ne 'printf "Position %d N %d\n", $-[0]+1, $+[0]-$-[0] while /N+/g'
另一种稍微快一点的方法(至少在我的版本中perl
)perl
使用 (实验性的)(?{...})
正则表达式运算符:
perl -ne '0 while /N(?{$s=pos})N*(?{printf "Position %d N %s\n", $s, pos()-$s+1})/g'
答案2
另一个awk
解决方案:
awk -F '' '{for(i=1;i<=NF;i++){ if($i=="N"&&!sPOS) sPOS=i;
if (i==NF &&sPOS && $NF=="N"){LN++}; if($i=="N" &&sPOS && i<NF) {LN++}
else if(sPOS) {printf("Position %d N %d\n", sPOS, LN); LN=sPOS=0} }
}' infile.txt
由于所有awk
实现都不支持空 FS ( -F ''
),因此下面是修改后的脚本以兼容:
awk -F'N' '{sPOS=0;for(i=2;i<=NF;i++){ if($i==""&&!sPOS) sPOS=(i-1)+length($(i-1));
if($i=="" &&sPOS && NF!=i) {LN++}
else if(sPOS) {printf("Position %d N %d\n", sPOS, ++LN); sPOS+=LN+length($i); LN=0} }
}' infile.txt
输入示例:
>sequence-1
ATCGCTAGCATNNNNNNNNNNNNNNCTAGCATCATGCNNNNNNATACGCATCACANNNNNNNNNCgcatATCACNN
N
AN
NNA
结果是:
Position 12 N 14
Position 38 N 6
Position 56 N 9
Position 75 N 2
Position 1 N 1
Position 2 N 1
Position 1 N 2