根据条件反转特定字段中的字符串

VPa*_*ler 5 bash perl awk bioinformatics dna-sequence

我有这个文件:

m64071_220512_054244/12584899/ccs rev pet047-10055 ACGTGCGACCTTGTGA TTGAGGGTTCAAACGTGCGACCTTGTGA
m64071_220512_054244/128321000/ccs rev pet047-10055 ACGTGCGACCTTGTGA TTGAGGGTTCAAACGTGCGACCTTGTGA
m64071_220512_054244/132186699/ccs fwd pet047-10055 TCACAAGGTCGCACGT TCACAAGGTCGCACGTTTGAACCCTCAA
m64071_220512_054244/134874748/ccs fwd pet047-10055 TCACAAGGTCGCACGT TCACAAGGTCGCACGTTTGAACCCTCAA
Run Code Online (Sandbox Code Playgroud)

仅当以下情况时,我才需要tr字段reverse$4 和 $5$2==rev

预计:

m64071_220512_054244/12584899/ccs rev pet047-10055 TCACAAGGTCGCACGT TCACAAGGTCGCACGTTTGAACCCTCAA
m64071_220512_054244/128321000/ccs rev pet047-10055 TCACAAGGTCGCACGT TCACAAGGTCGCACGTTTGAACCCTCAA
m64071_220512_054244/132186699/ccs fwd pet047-10055 TCACAAGGTCGCACGT TCACAAGGTCGCACGTTTGAACCCTCAA
m64071_220512_054244/134874748/ccs fwd pet047-10055 TCACAAGGTCGCACGT TCACAAGGTCGCACGTTTGAACCCTCAA
Run Code Online (Sandbox Code Playgroud)

我试过:

perl -lpe 'if(/rev/) {$rev=/rev/;next}; if ($rev) {$F[4,5]=~tr/ATGC/TACG/; $F[4,5]=reverse $F[4,5]; print "@F"}' file 
Run Code Online (Sandbox Code Playgroud)

我还尝试使用 Awk (在 awk 中执行 bash 命令并打印命令输出

awk '{
            if($2==rev)
        {
            cmd1="echo \047" $4 "\047 | rev | tr \047ATGC\047 \047TACG\047" 
            cmd2="echo \047" $5 "\047 | rev | tr \047ATGC\047 \047TACG\047"
            newVar1=((cmd1 | getline line) > 0 ? line : "failed") 
            newVar2=((cmd2 | getline line) > 0 ? line : "failed")
            close(cmd)
            print $1, $2, $3, newVar1, newVar2
        }
        else {print}
}' file
Run Code Online (Sandbox Code Playgroud)

zdi*_*dim 4

要遵循问题的尝试:

\n
perl -w -lanE\'\n    if ($F[1] eq "rev") { \n        for (@F[3,4]) { tr/ATGC/TACG/; $_ = reverse $_ } \n    } \n    say "@F"\n\' file\n
Run Code Online (Sandbox Code Playgroud)\n

可以将其放在一行中,为了便于阅读,我将其展开(或将其按原样复制粘贴到大多数 shell 中)。或者,当然,将其放入程序文件中,特别是如果还有更多事情要做的话。

\n

元素循环块中的代码@F[3,4]在数组的每个元素上运行,并就地修改它(因为$_只是数组元素的别名),首先是tr然后通过(反转和)分配。所有这些也可以写成

\n
$_ = reverse tr/ATGC/TACG/r  for @F[3,4];\n
Run Code Online (Sandbox Code Playgroud)\n

修饰符r使tr返回更改后的字符串,然后对其进行reverse-ed,然后通过$_别名将其分配回当前处理的数组元素

\n

对问题中代码的评论

\n
    \n
  • 要将输入字符串分解为@F数组(“自动拆分”),需要-a标志

    \n
  • \n
  • 由于您明确打印需要的内容,因此使用-n标志,而不是-p

    \n
  • \n
  • 该行中的字段 4 和 5 是数组元素 3 和 4

    \n
  • \n
  • 我假设$F[4,5]你指的是两个数组元素(应该是 3,4)。那么,应该是@F[3,4]——并且带有-w标志,对于警告,我们会听到它

    \n
  • \n
  • 更重要的是,我们不能将正则表达式或模式绑定tr到列表,而只能绑定到单个标量。\xe2\x80\xa0 为了将其应用于tr多个项目,需要迭代它们,如上所示

    \n
  • \n
\n
\n

\xe2\x80\xa0 随着@ary =~ /.../LHS 首先被评估,所以我们得到类似的东西

\n
$ary[0], ..., $ary[-1] =~ /.../;\n
Run Code Online (Sandbox Code Playgroud)\n

直到最后一项的所有术语都在 void 上下文中进行评估并被丢弃(请参阅逗号运算符以了解其逻辑),逐一并带有警告(如果警告打开!),然后$ary[-1] =~ /.../进行评估并从整个表情。

\n

这同样适用LIST =~ /.../;(无论是否有括号LIST

\n