bash - awk sub() 按位置获取子字符串

标签 bash awk

如果我有以下内容:

>ID_10_J_X
ABCDEFGHIJKLMNOPQRSTUVQXYZ

(即 fasta 文件!)

我希望能够根据位置(第一个元素的第二个元素,即 10)定位子字符串,并在其周围取 n 个位置,即 5 个位置

EFGHIJKLMNO

然后用第 1 行的第 4 个元素替换感兴趣的位置 - 即 X:

EFGHIXKLMNO

我可以找到子字符串,这很好...但是我在使用第 1 行的元素在第 2 行中进行替换时遇到了麻烦。我有以下代码:

#!/bin/bash

awk '

/>/{split($0,M,"_")}     
!/^>/{split($1,N,"")
print M[1]"_"M[2]"_"M[3]"_"M[4]"\n"substr($1,M[2]-5,10)}

' $1

这让我得到了我的子字符串。

有人可以帮我解释一下我的逻辑来进行替换吗?我想我可以使用 sub() 函数并直接调用子字符串。我的想法是使用:

sub(regex/position,replacement,target)

在我的示例中将翻译为:

sub(N[2],N[4],substr($1,M[2]-5,10))

尝试这个结果

awk: cmd. line:5: print sub(M[2],M[4],substr($1,M[2]-10,20))}
awk: cmd. line:5:                                          ^ sub third parameter is not a changeable object

所以看来我无法显式调用子字符串,而且我也怀疑是否能够在正则表达式参数中使用位置元素。

有人可以帮我编写代码以形成通用解决方案吗?我的输入是

>ID_10_J_X
ABCDEFGHIJKLMNOPQRSTUVQXYZ

所需的输出是:

EFGHIXKLMNO

我将在同一个文件中有许多输入。

还必须成立的是,虽然我正在寻找由第 1 行中给出的位置两侧的 5 个位置组成的子字符串,但如果第 1 行中的位置 < 5,则必须在指定位置进行替换即

>ID_2_J_X
ABCDEFGHIJKLMNOPQRSTUVQXYZ

AXCDEFG

如果最终的子字符串始终具有一定的长度,即如果我指定了 10 个子字符串,但替换位于上面的位置 2,则在替换完成后会选择 8 个字符,这会很好(但不是必需的)长度为10的子串

谢谢

最佳答案

这个 awk 脚本会产生您想要的输出:

awk -F_ '/^>/{p=$2;s=$NF;next}{print substr($0,p-5,5) s substr($0,p+1,5)}' file

第一个 block 保存您的位置p和替换字符s。第二个打印 p 之前的 5 个字符(替换字符),然后打印 p 之后的 5 个字符。

演示:

$ cat file
>ID_10_J_X
ABCDEFGHIJKLMNOPQRSTUVQXYZ
$ awk -F_ '/^>/{p=$2;s=$NF;next}{print substr($0,p-5,5) s substr($0,p+1,5)}' file
EFGHIXKLMNO

下面是代码的更新版本,用于处理距行首或行尾 5 个字符以内的位置。由于它稍长一些,为了清晰起见,我使用了脚本而不是单行文字。您可以像 awk -f script.awk file 一样运行它:

BEGIN { FS="_" }
/^>/ {
    p=$2; c=$NF; next
}
{
    if (p-5<1) s=1
    else if (p+5>length($0)) s=length($0)-10
    else s=p-5
    print substr($0,s,p-s) c substr($0,p,11-p+s)
}

测试一下:

$ cat file
>ID_2_J_X
ABCDEFGHIJKLMNOPQRSTUVQXYZ
>ID_10_J_X
ABCDEFGHIJKLMNOPQRSTUVQXYZ
>ID_22_J_X
ABCDEFGHIJKLMNOPQRSTUVQXYZ
$ awk -f script.awk file
AXBCDEFGHIJK
EFGHIXJKLMNO
PQRSTUXVQXYZ

关于bash - awk sub() 按位置获取子字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29165703/

相关文章:

java - 无法在java代码中运行命令

bash - Bash:如何在sqlite3中插入具有特殊字符的文本?

regex - awk sub 用一个捕获组替换成

awk:从输入打印匹配组

csv - 重击 : Add empty column(s) to CSV with unknown positions

bash - 列出按 p4 中未决更改列表分组的打开文件

bash 动态创建变量

linux - 将模式的奇数和偶数出现替换为另一个相同的模式

linux - 包含 CSR 的 POST 请求在 Bash 中失败

bash - awk 在脚本中更改工作目录