经过一番处理后,我最终得到了一个像这样的文件:
ALA 251
VAL 252
TYR 253
LYS 254
SER 255
ALA 256
ALA 257
MET 258
LEU 259
ASP 260
MET 261
THR 262
GLY 263
ALA 264
GLY 265
TYR 266
VAL 267
TRP 268
我们将第一列称为“res”,将第二列称为“num”。请注意,“res”始终由 3 个字母组成,“num”由 1 到 4 个数字组成。
我正在寻找一种方法来提取与由四个连续“res”组成的精确列模式的第一个“res”相对应的位置(列“num”的值),如下所示:
TYR
LYS
SER
ALA
在这种情况下,根据文件和指示的模式,输出应为:
253
我用 awk 进行了多次尝试。看起来应该是可行的,但目前我的技术还不够。如果有任何优秀的用户对此提出建议,我将不胜感激。
答案1
答案2
滑动窗口sed
:
解析.sed
# Establish the sliding window
1N
2N
# Maintain the sliding window
N
# Match the desired pattern to the current window
/^TYR \(.*\)\nLYS .*\nSER .*\nALA .*$/ {
h; # Save the window in hold space
s//\1/p; # Extract desired output
x; # Re-establish window
}
# Maintain the sliding window
D
像这样运行它:
sed -nf parse.sed infile
输出:
253
答案3
与中相同的方法斯蒂芬·基特的回答,但没有附加seq
变量。相反,连续的“数字”用于确定当前行是否属于我们正在查找的集合。
awk '{
if ($1=="TYR") {
i=$2 # remember index
}
else if (i!=0) {
if ($2==i+1 && $1=="LYS" || $2==i+2 && $1=="SER" || $2==i+3 && $1=="ALA") {
if ($2==i+3) { # are we there yet?
print i; exit
}
}
else {
i=0 # nope, reset index
}
}
}' file
(为了可读性保留了不需要的花括号和缩进)
答案4
您可以使用滑动窗口来做到这一点:
解析.awk
# Split the pattern into the `p` array and remember how many there are in `n`
BEGIN { n = split(pat, p, "\n") }
# Collect n lines into the `A` array
NR <= n { A[NR] = $0; next }
# Maintain the sliding window after n lines
NR > n {
for(i=2; i<=n; i++)
A[i-1] = A[i]
A[n] = $0
}
# Test if the current window contains the pattern
{
hit = 1
for(i=1; i<=n; i++) {
split(A[i], x)
if(x[1] != p[i]) {
hit = 0
break
}
}
# If the window matches print the second column
if(hit) {
split(A[1], x)
print x[2]
}
}
像这样运行它:
awk -v pat="$(< patternfile)" -f parse.awk infile
输出:
253