ускорить мою команду awk? Ответ должен быть awk :) - PullRequest
0 голосов
/ 30 марта 2012

У меня есть некоторый awk-код, который работает очень медленно. Формат моего файла - 5 колонок ASCII с разделителями табуляции. Я работаю со столбцом 5, чтобы получить количество соответствующих символов для изменения значения в столбце 4.

Пример строки ввода:

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

Если я найду «^» в $ 5, я не хочу считать его или следующий символ. Затем я хочу узнать, сколько символов ">" или "<" или "*" и удалить их из подсчета. Я предполагаю, что использование gsub и 3-х разбиений - это далеко не идеально, тем более что столбец 5 может иногда быть очень очень длинной строкой. </p>

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 ]

1 голос
/ 30 марта 2012

Вот предположение:

awk '
    BEGIN {FS = OFS = "\t"}
    {
        str = $5
        gsub(/\^.|[><*]/, "", str)
        l = length(str)
    }
'
1 голос
/ 30 марта 2012

Вам нужно использовать awk, или это будет работать вместо этого?

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

Перевод:

  • Извлечение 5-го поля из табуляции $file.
  • Удалить все поля, начинающиеся с заглавной буквы.
  • Удалите символы <, >, * и символы новой строки.
  • Подсчитайте оставшиеся символы.
1 голос
/ 30 марта 2012

Как я вижу, ваш шаблон gsub не будет работать, так как / не был закрыт. В любом случае, если я правильно понял, и вам нужно количество символов $5 без каких-либо символов, я бы выбрал:

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

Вы должны перечислить свои пропускаемые символы между [ и ], и не начинаться с ^!

0 голосов
/ 30 марта 2012

Это может работать для вас:

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'
...