2015-11-24 3 views
1

У меня есть вход, как это:AWK: посмотрите на следующие несколько строк, не изменяя NR

touchDown(9, 296, 413); 
usleep(49699.75); 
touchUp(9, 295, 413); 
usleep(880305.71); 

touchDown(9, 282, 397); 
touchDown(10, 310, 536); 
usleep(66298.79); 
touchUp(9, 283, 402); 
touchUp(10, 312, 538); 
usleep(1300114.83); 

touchDown(2, 313, 634); 
touchDown(3, 257, 341); 
touchDown(11, 349, 474); 
touchMove(3, 69, 637); 
usleep(16339.04); 
touchMove(3, 34, 477); 
usleep(49276.96); 
touchUp(2, 311, 633); 
touchUp(3, 253, 341); 
touchUp(11, 344, 475); 

Теперь я хочу, например. чтобы посмотреть, есть ли блок (который всегда начинается с/touchDown /) имеет/touchMove/где-то в нем. Если это так, не печатайте блок или не редактируйте его каким-либо образом. Но awk проходит по строкам, и кажется, нет способа получить несколько строк назад, как только эти строки обрабатываются.

Я думал, что функция getline мне поможет, но похоже, что она также увеличивает NR. Некоторые решения, которые я нашел здесь, где поставить предыдущую строку в переменной, которая может быть в порядке только для одной строки, но если такой блок проходит через многие строки, это кажется очень неудобным.

Это «вы не можете вернуться назад» из AWK просто портит мне ...

У вас есть решение для этого? Или другой язык лучше для таких вещей?

Спасибо

+0

Что определяет «блок»? Пустые строки? Что вам нужно делать * с этими «блоками», как только вы их идентифицировали/нашли? –

+0

Получите книгу «Эффективное программирование Awk», 4-е издание, Арнольдом Роббинсом, поскольку вам не хватает некоторых основных принципов awk, в том числе самого важного: awk ориентирован на запись, а не ориентирован на линию, он по умолчанию разделяет записи по новостям. Если вы когда-либо рассматриваете возможность использования 'getline', убедитесь, что вы сначала прочитали и полностью поняли весь документ по адресу http://awk.info/?tip/getline, а затем обычно не используете его.Нет лучшего языка для текстовых манипуляций, вам просто нужно узнать, как это работает, а не пытаться заставить его действовать так, как вы думаете. –

+1

@ EdMorton Да, очень верно. Я, как правило, собираю свои знания, я должен быть более систематичным, и мне будет легче. :) – Blubberlase

ответ

2

Имея, что запись определяется пустая строка и поле ограничена одной строки, вы можете использовать следующую awk команду:

awk '{for(i=1;i<=NF;i++){if($i~/^touchMove/){print;next}}}' FS='\n' RS='\n\n' 

команда проверяет каждое поле, если оно начинается с touchMove и печатает всего запись в этом случае.

Это может быть также упрощено до:

awk '/\ntouchMove/' FS='\n' RS='\n\n' 

что означает печать запись, если она содержит термин «TouchMove» после перевода строки


После EtanReisner's comment мы можем упростить даже выше, до:

awk '/\ntouchMove/' RS='' 

с:

EtanReisner

RS = '' наборы AWK в режиме "пункт", который разграничивает вход с пустыми строками тоже. Он также автоматически использует новые строки для FS (в дополнение к любому одиночному символу, установленному FS). Так FS = '\ п' RS = '\ п \ п' может быть заменен только с RS = ''

https://www.gnu.org/software/gawk/manual/html_node/Multiple-Line.html

Спасибо за это!

+1

'RS = ''' устанавливает awk в режим абзаца, который также ограничивает ввод пустыми строками. Он также автоматически использует символы новой строки для 'FS' (в дополнение к любому одиночному символу, для которого установлен' FS'). Поэтому 'FS = '\ n' RS = '\ n \ n'' можно заменить просто« RS = ». –

+0

@ EtanReisner Действительно ?? Ницца! :) – hek2mgl

+0

Yup. См. [Многострочные записи] (https://www.gnu.org/software/gawk/manual/html_node/Multiple-Line.html), например. –

Смежные вопросы