加快我的awk命令?答案必须是awk :)

时间:2012-03-30 15:52:00

标签: bash split awk gsub

我有一些运行速度非常慢的awk代码。我的文件格式是制表符分隔5列ASCII。我在第5列上操作以获取适当字符的计数以更改第4列中的值。

示例输入行:

  

10 5134832 N 28 Aaaaa * AAAAaAAAaAAAAaAAAA ^] a ^] a ^ Fa ^] a

如果我在$ 5中找到任何“^”,我想不计算它,或者以下字符。 然后我想知道有多少个字符是“>”或“<”或“*”并将其从计数中删除。我猜测使用gsub,并且3次拆分不太理想,特别是因为第5列偶尔可能是一个非常长的字符串。

awk '{l=$4; if($5~/>/ || $5~/</ || $5~/*/ )  {gsub(/\^./,"");l-=split($5,a,"<")-1;l-=split($5,a,">")-1;l-=split($5,a,"*")-1}

如果代码在上面的行上成功运行,则l将为27。

我省略了命令的周围部分,试着把注意力集中在我有问题的部分。

那么,让这种运行更快的最佳步骤是什么?

4 个答案:

答案 0 :(得分:1)

我认为,gsub模式不起作用,因为/未关闭。无论如何,如果我正确地得到它并且你想要$5没有一些字符的字符数,我会选择:

count=length(gensub("[><A-Z^]","","g",$5))

您应该在[]之间列出可跳过的字符,而不是以^开头!

答案 1 :(得分:1)

这是一个猜测:

awk '
    BEGIN {FS = OFS = "\t"}
    {
        str = $5
        gsub(/\^.|[><*]/, "", str)
        l = length(str)
    }
'

答案 2 :(得分:1)

您是否需要使用awk,或者这会改变吗?

cut -f 5 < $file | grep -v '^[A-Z]' | tr -d '<>*\n' | wc -c

翻译:

  • 从制表符分隔的$file中提取第5个字段。
  • 删除以大写字母开头的所有字段。
  • 删除字符<>*和换行符。
  • 计算剩余的字符数。

答案 3 :(得分:0)

这可能对您有用:

echo "10 5134832 N 28 Aaaaa*AAAAaAAAaAAAAaAAAA^]a^]a^Fa^]a" |
awk '/[><*^]/{t=$5;gsub(/[><*]|[\^]./,"",t);$4=length(t)}1' 
10 5134832 N 27 Aaaaa*AAAAaAAAaAAAAaAAAA^]a^]a^Fa^]a

如果你想显示修改后的第五个字段:

 awk '/[><*^]/{gsub(/[><*]|[\^]./,"",$5);$4=length($5)}1'