我有一些运行速度非常慢的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。
我省略了命令的周围部分,试着把注意力集中在我有问题的部分。
那么,让这种运行更快的最佳步骤是什么?
答案 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'