更快的方式来通过awk而不是shell中的嵌套if循环

时间:2018-04-12 15:21:26

标签: shell if-statement awk nested

我有以下代码

if [[ $intron_exon =~  E ]] ; then 
  upstream=$exon_id":I"$upstream_no
  downstream=$exon_id":I"$exon_number
    #nested in above if condition
    if grep -q -e "$upstream" Transcriptome.txt   ; then
     Up=$upstream
    fi
    #nested in above if condition
    if grep -q -e  "$downstream" Transcriptome.txt  ; then
     Down=$downstream
   fi
else 
  upstream=$exon_id":E"$upstream_no
  downstream=$exon_id":E"$exon_number
   #nested in above else condition
   if grep -q -e "$upstream" Transcriptome.txt  ; then
    Up=$upstream
   fi
   #nested in above else condition
   if  grep -q -e "$downstream" Transcriptome.txt  ; then
    Down=$downstream
   fi
fi

我要做的是检查变量是否等于E,如果是,则检查上游和下游是否存在(注意我在主if和else中以不同方式初始化上游和下游);如果不是E,那么我以不同方式初始化上游和下游,并检查它们是否存在于文件中。

3 个答案:

答案 0 :(得分:2)

如果你想重构,你可以写

[[ $intron_exon == *E* ]] && key=I || key=E

upstream=$exon_id:$key$upstream_no
grep -q -F "$upstream" Transcriptome.txt && Up=$upstream || Up="default up"

downstream=$exon_id:$key$exon_number
grep -q -F "$downstream" Transcriptome.txt && Down=$downstream || Down="default down"

我假设你想要grep的固定字符串匹配。

答案 1 :(得分:1)

Transcriptome.txt有多大?这看起来像是你的主要瓶颈。其次,你在重复自己。

如果我们简化一下,我们得到:

if [[ $intron_exon =~ E ]]; then
  upstream=$exon_id":I"$upstream_no
  downstream=$exon_id":I"$exon_number
else
  upstream=$exon_id":E"$upstream_no
  downstream=$exon_id":E"$upstream_no
fi
# greps go here.

所以现在我们已经重构了,如果我们能加快速度,我们只需要做一次。 (你可以进一步重构上面的内容,因为唯一的区别是I vs E,所以你可以使用另一个变量。)

这里的一个技巧是使用awk打印出你的Up和Down分配,然后执行它,例如:

eval $(awk ...)

所以现在的诀窍是让awk循环并在匹配时打印出所需的代码。这样的事情就足够了:

awk -e "/$upstream/{print \"Up=$upstream;\"} /$downstream/{print \"Down=$downstream;\"}" Transcriptome.txt

这将最终打印多个UpDown,但最终结果实际上并不重要。

缺点是,即使您提前找到了上下字段,也会读取整个文件。

(可能有一种方法可以让awk在找到两者后提前终止,但你必须确定这是否值得。)

把它放在一起,我们得到:

if [[ $intron_exon =~ E ]]; then
  upstream=$exon_id":I"$upstream_no
  downstream=$exon_id":I"$exon_number
else
  upstream=$exon_id":E"$upstream_no
  downstream=$exon_id":E"$upstream_no
fi
eval $(awk -e "/$upstream/{print \"Up=$upstream;\"} /$downstream/{print \"Down=$downstream;\"}" Transcriptome.txt)

答案 2 :(得分:1)

这可能是你要找的东西:

awk -v intron_exon="$intron_exon" \
    -v exon_id="$exon_id" \
    -v upstream_no="$upstream_no" \
    -v exon_number="$exon_number" '
BEGIN {
    pfx = (intron_exon ~ /E/ ? ":I" : ":E")
    upstream   = exon_id pfx upstream_no
    downstream = exon_id pfx exon_number
}
$0 ~ upstream   { gotUp = 1 }
$0 ~ downstream { gotDn = 1 }
gotUp && gotDn  { exit      }
END {
    print (gotUp ? upstream   : "some_default_value")
    print (gotDn ? downstream : "some_default_value")
}
' file

这实际上取决于你脚本的其余部分。