如何计算序列中任意位置的 C/T 最长连续模式以及从中心算起的 C/T 最长连续模式
CCCCTGTTGCCAAACAATGC
TTTTCCCGCCTTTGGCCTAC
TACACGGAACCTCTTTTTTTA
所需的输出是计算序列中任意位置的 C/T 最长连续模式以及从中心开始的 C/T 最长连续模式
CCCCTGTTGCCAAACAATGC5 2
TTTTCCCGCCTTTGGCCTAC7 5
TACACGGAACCTCTTTTTTTA10 10
第一行在序列中有 5 个连续的 C/T 模式,而从中心开始最长的 C/T 模式是 2。
附言。类似问题的解决方案在这里 计算最长的连续模式
答案1
我假设你所说的“从中心”是“包含字符串中间字符的序列。我在测试数据中添加了一行,使得字符串的中间字符既不是 C 也不是 T:
$ cat file
CCCCTGTTGCCAAACAATGC
TTTTCCCGCCTTTGGCCTAC
TACACGGAACCTCTTTTTTA
CATAAAAAAAAAAAAACTCT
该解决方案依赖于 awk 的 RSTART 和 RLENGTH 变量,这些变量被设置为匹配模式的 match() 函数的副产品,以及一些算法来跟踪我们在字符串中的位置:
awk '{
line = $0
max = max_ctr = 0
mid = int(length($0)/2)
idx = 1
while (match( substr(line,idx), /[CT]+/ )) {
if (RLENGTH > max) max = RLENGTH
if (idx <= mid && mid <= idx+RLENGTH) max_ctr = RLENGTH
idx += RSTART + RLENGTH - 1
}
print $0, max, max_ctr
}' file
输出
CCCCTGTTGCCAAACAATGC 5 2
TTTTCCCGCCTTTGGCCTAC 7 5
TACACGGAACCTCTTTTTTA 10 10
CATAAAAAAAAAAAAACTCT 4 0
答案2
如果“从中心”意味着“最接近中心但不一定穿过它的最长字符串”,您可以尝试
awk '
{MID = int(length()/2);
MX = PTR = 0
T0 = $0
while (match ($0, /[CcTt]+/)) {if (RLENGTH > MX) MX = RLENGTH
SSTR = PTR + RSTART
SEND = SSTR + RLENGTH - 1
TMPS = SSTR - MID
TMPE = MID - SEND
if (SEND < MID) {P = TMPE; RES = RLENGTH}
else {if (SSTR <= MID) {P = 0; RES = RLENGTH}
else if ((P > TMPS) ||
(P == TMPS) && (RLENGTH > RES)) {P = TMPS; RES = RLENGTH}
}
PTR = SEND
$0 = substr ($0, RSTART + RLENGTH)
}
print T0, MX, RES
}
' file
它循环从正则表达式到正则表达式匹配的行,并保留一个指针来保存原始行中的位置。由此,它计算从字符串末尾到中心或从中心到字符串开头的字符距离,并将最小距离的字符串长度分配给结果变量。对于相等的距离,它保留最长的长度。
对于穿过中心的图案,结果与之前给出的样本相同。