Sed bash字符串中模式的条件替换取决于字符串的开头

Sed bash字符串中模式的条件替换取决于字符串的开头,sed,Sed,我是bash的新手,所以请原谅我没有使用正确的术语 我需要在一组文件中替换六个字符的特定模式。按顺序替换的模式取决于每个文本字符串的开头 这是一个输入示例: chr1:123-123 5GGGTTAGGGTTAGGGTTAGGGTTAGGGTTA3 chr1:456-456 5TTAGGGTTAGGGTTAGGGTTAGGGTTAGGG3 chr1:789-789 5GGGCTAGGGTTAGGGTTAGGGTTA3 chr1:123-123etc是字符串的名称,它们通过一个选项卡与我需

我是bash的新手,所以请原谅我没有使用正确的术语

我需要在一组文件中替换六个字符的特定模式。按顺序替换的模式取决于每个文本字符串的开头

这是一个输入示例:

chr1:123-123 5GGGTTAGGGTTAGGGTTAGGGTTAGGGTTA3

chr1:456-456 5TTAGGGTTAGGGTTAGGGTTAGGGTTAGGG3 

chr1:789-789 5GGGCTAGGGTTAGGGTTAGGGTTA3
chr1:123-123
etc是字符串的名称,它们通过一个选项卡与我需要使用的字符串分开。我需要使用的字符串由字符5和3分隔,但我可以更改它们

我想用
X
TTAGGG
TAGGG
TAGGG
AGGGTT
GGGTTA
GGGTTA
GGTTAG

类似地,包含
CTAGGG
的模式(如第3行)的顺序与前一个类似,将被替换为不同的字符。 游戏重复进行,每个模式的6个角色都有一些特殊的差异。 我开始写这样的东西:

#!/bin/bash
NORMAL=`echo "\033[m"`
RED=`echo "\033[31m"` #red

#read filename for the input file and create a copy and a folder for the output
read -p "Insert name for INPUT file: " INPUT
echo "Creating OUTPUT file " "${RED}"$INPUT"_sub.txt${NORMAL}"
mkdir -p ./"$INPUT"_OUTPUT
cp $INPUT.txt ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
echo 
#start the first set of instructions
perfrep
#starting a second set of instructions to substitute pattern with one difference from TTAGGG
onemism
说明是

perfrep() {
    sed -i -e 's/TTAGGG/X/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
    sed -i -e 's/TAGGGT/X/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
    sed -i -e 's/AGGGTT/X/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt 
    sed -i -e 's/GGGTTA/X/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt     
    sed -i -e 's/GGTTAG/X/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt     
    sed -i -e 's/GTTAGG/X/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
}

# starting a second set of instructions to substitute pattern with one difference from TTAGGG
onemism(){
    sed -i -e 's/[GCA]TAGGG/L/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
    sed -i -e 's/G[GCA]TAGG/L/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
    sed -i -e 's/GG[GCA]TAG/L/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
    sed -i -e 's/GGG[GCA]TA/L/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
    sed -i -e 's/AGGG[GCA]T/L/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
    sed -i -e 's/TAGGG[GCA]/L/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
}
我还需要用
T[GCA]AGGG
TT[TCG]GG
TTA[ACT]GG
TTAG[ACT]G
TTAGG[ACT]
重复

通过这个过程,我得到了所示输入的这些结果

5GGGXXXXTTA3

5XXXXX3 

5GGGLXXTTA3
在我看来,对于我的工作,第一个和第二个字符串都是由X重复五次组成的,字符的顺序只是略有不同。另一方面,第三个可以这样伪装:

5LXXX3
如何告诉脚本,如果字符串以5ggtta而不是5TTAGGG开头,则必须以

sed -i -e 's/GGGTTA/X/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
而不是

sed -i -e 's/TTAGGG/X/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
?

我将需要对所有案例进行重复;例如,如果字符串以GTTAGG开头,我需要以

sed -i -e 's/GTTAGG/X/g' ./"$INPUT"_OUTPUT/"$INPUT"_sub.txt
等等,再加上我的模式的一些变化

我需要用
TTAGGG
重复替换和输入文件所有行的变体

很抱歉问了这么长的问题。谢谢大家

添加Varun询问的信息

6个字符的模式将是
TTAGGG
TTAGG
T[GCA]AGGG
TT[TCG]GGG
TTA[ACT]GG
TTAG[ACT]G
TTAGG[ACT]
。 必须针对不同的帧检查每个帧,例如,对于
TTAGGG
我们有6个帧
TTAGGG
GTTAGG
GGTTAG
GGGTTA
AGGGTT
TAGGGT
。 相同的框架必须应用于包含可变位置的图案

我将总共检查42个模式,分为7组:一组包含
TTAGGG
和衍生帧,6组包含位置可变的模式及其衍生帧。
TTAGGG
和衍生品是最重要的,需要首先检查。

#/usr/bin/awk-f
#! /usr/bin/awk -f

# generate a "frame" by moving the first char to the end
function rotate(base){ return substr(base,2) substr(base,1,1) }

# Unfortunately awk arrays do not store regexps 
# so I am generating the list of derivative strings to match
function generate_derivative(frame,arr,  i,j,k,head,read,tail) {
    arr[i]=frame;
    for(j=1; j<=length(frame); j++) {
        head=substr(frame,1,j-1);
        read=substr(frame,j,1);
        tail=substr(frame,j+1);
        for( k=1; k<=3; k++) {
           # use a global index to simplify
            arr[++Z]= head substr(snp[read],k,1) tail
        }
    }
}

BEGIN{
    fs="\t";
   # alternatives to a base
   snp["A"]="TCG"; snp["T"]="ACG"; snp["G"]="ATC";  snp["C"]="ATG"; 

    # the primary target
    frame="TTAGGG";
    Z=1; # warning GLOBAL
    X[Z] = frame;
    # primary derivatives
    generate_derivative(frame, X);
    xn = Z;

    # secondary shifted targets and their derivatives
    for(i=1; i<length(frame); i++){
        frame = rotate(frame);
        L[++Z] = frame;
        generate_derivative(frame, L);
    }
}

/^chr[0-9:-]*\t5[ACTG]*3$/ {

    # because we care about the order of the prinary matches
    for (i=1; i<=xn; i++) {gsub(X[i],"X",$2)}
    # since we don't care about the order of the secondary matches
    for (hit in L) {gsub(L[hit],"L",$2)}
    print
}
END{
    # print the matches in the order they are generated
    #for (i=1; i<=xn; i++) {print X[i]};
    #print ""
    #for (i=1+xn; i<=Z; i++) {print L[i]};
}
#通过将第一个字符移动到末尾来生成“帧” 函数rotate(base){返回substr(base,2)substr(base,1,1)} #不幸的是,awk数组不存储regexp #因此,我将生成要匹配的派生字符串列表 函数生成_导数(帧、arr、i、j、k、头、读、尾){ arr[i]=帧;
对于(j=1;jonce)您开始回溯(更改应用规则的顺序),您正在推动在sed中使用正则表达式应该做的事情,这在流的单次传递中是最好的。此外,AGGG对我来说没有意义虽然这不能回答您的问题,但没有必要(通常)在同一个文件上运行多个sed实例(如上所述)。给定较大的文件,您可以通过在对sed的一次调用中“链接”多个替换来显著减少运行时间,即
sed-i's/TTAGGG/X/g;s/TAGGGT/X/g;s/AGGGTT/X/g;…'文件
(通常不需要
-e
)。祝你好运。@tomc,谢谢你的评论。这是一个非常原始的脚本版本,我会在以后进行优化。另外,刚开始使用bash,我对命令的规则或最佳解决方案一无所知。AGGG是一个错误,应该是AGGGTT。@shellter感谢你对多个实例的更正。好的,如前所述是的,你的Q(IMHO;-)中有太多的信息。用一段代码将其归结为一个问题。让它发挥作用,它可能会给你解决其他问题的洞察力,或者如果你陷入困境,然后发布另一个小问题(er)问:根据需要重复。或者在上完成
sed
教程。也同意tomc的评论,sed可能不是你的游戏结束工具集。祝你好运。感谢你的代码。最后,在阅读你的答案之前,我能够运行一个脚本,其中包含大量的框架条件语句和多个sed,以及我亲手编写的模式。这很好它似乎可以工作,但速度非常慢,当插入更改序列的帧时,它无法正确替换…除了是一个非常长的脚本之外。我将尝试将部分代码发布到某个地方。