2012-03-30 2 views
0

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

Примера входных данные линия:

10 5134832 Н 28 Ааааа * AAAAaAAAaAAAAaAAAA ^] а ^] а^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} 

Если код успешно работает на указанной выше линии, л будет 27.

Я опуская окружающие части команды, чтобы попытаться сосредоточиться на части у меня есть вопрос о том.

Итак, что является лучшим шагом для ускорения этого запуска?

+0

перепишем его в ассемблере :) –

ответ

1

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

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

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

+0

спасибо Жолт. Добавленный трюк заключается в том, что наряду с отсутствием некоторых отдельных символов я хочу опустить любые пары символов «^ [A-Z]» – lonestar21

+1

Что вы подразумеваете под символьными парами? –

+0

Я отредактировал вопрос, чтобы показать, что я имею в виду под символьными парами. Выше я хочу опустить «^]» и «^ F» из моего подсчета. – lonestar21

1

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

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

Как правило, gsub на нескольких charaters должен быть быстрее, чем несколько разделов? – lonestar21

+0

@ lonestar21, не знаю, попробуй и посмотри. С несколькими разбиениями awk необходимо создать несколько массивов в памяти. –

+0

@ lonestar21, обновленный, чтобы отразить ваше обновление вопроса –

1

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

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

Перевод:

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

Мне нужно использовать awk, так как это часть большей команды awk. – lonestar21

+1

Хорошо. Но справедливое изменение спецификаций в вопросе _after_ ответов опубликовано! ;-) –

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' 
Смежные вопросы