2017-02-14 8 views
2

Предполагая, у меня есть входной файл, содержимое которогоAwk GetLine() функция не работает на пустых строках

cat file 


[source,I] 

[source,more] 

[source,1234] 

[source,content] 

Обратите внимание на две пустые строки первого следуют шаблону, начиная с [source, а затем единую пустую строку из последующего и далее. Я хочу удалить один или несколько пустых строк, за которыми следует узор (или, альтернативно, положить, удалить одну пустую строку поверх рисунка, начиная с [source). Я хочу, чтобы выход в

[source,I]  
[source,more]  
[source,1234]  
[source,content] 

Я выработал Awk логику

awk '!NF{getline n; if (match(n, /^\[source/)) {print n}}' file 

который работал отлично за исключением того, что пропустил шаблон, который следовал за две пустые строки и производится выход в

[source,more] 
[source,1234] 
[source,content] 

Я пробовал, почему вызов getline() был неудачным, напечатав линию NR, на которой Awk должен был сделать match() и напечатал линию,

awk '!NF{getline n; if (match(n, /^\[source/)) {print n} else {print NR}}' file 
2    # Why did this fail for NR==2? 
[source,more] 
[source,1234] 
[source,content] 

Хотите знать, почему он не для NR==2 когда getline() должен был возвратить [source,I] и печататься же после сопоставления с регулярным выражением.

$ awk --version 
GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.4-p1, GNU MP 6.1.1) 
+1

Вы можете получить нужный результат из этого входного файла только с помощью 'awk 'NF' file'. Если это еще не все, что вы пытаетесь сделать, обновите вопрос, чтобы исходный текст лучше представлял вашу реальную проблему. –

+1

@EdMorton: Обновите его сейчас! – Inian

ответ

3

Вы можете увидеть, что происходит, если вы добавите отладки печатает фронт:

$ awk '{print ">", NR, NF, $0} !NF{getline n; if (match(n, /^\[source/)) {print n} else {print NR}}' file 
> 1 0 
2 
> 3 1 [source,I] 
> 4 0 
[source,more] 
> 6 0 
[source,1234] 
> 8 0 
[source,content] 

Так AWK читает строки 1, который пуст, так !NF верно, так что делает GetLine читать строки 2, который также пуст, он не соответствует() и вместо этого печатает номер текущей строки, который равен 2.

Теперь awk читает строку 3, [source,I], которая не пуста, поэтому !NF является ложным, поэтому блок действия не выполняется и эта 3-я строка просто отбрасываются.

Теперь awk читает строку 4 .... и так далее.

Конечно, getline - это неправильный подход к такой проблеме, и если вы измените свой ввод/вывод образца, мы можем точно показать вам, как делать то, что вы хотите, но это SOUNDS, re действительно пытается:

$ awk 'NF{if (/^\[source/) print buf $0; buf=""; next} {buf = buf $0 ORS}' file 


[source,I] 

[source,more] 

[source,1234] 

[source,content] 
+1

Thanks Ed, пропустил часть с функцией 'getline()' (действительно тривиальной) после строки 1 и с одним вызовом линии, строка 3 анализируется! ошибочно полагал, что он будет анализировать строку 2 и читать строку 3 в качестве следующего результата получения строки. (Надеюсь, что я имел смысл с комментарием) – Inian

+0

Да, использование 'getline' - это сложный материал, поэтому я написал http://awk.freeshell.org/AllAboutGetline и включил пару ситуаций, в которых вы ДОЛЖНЫ использовать его. –

+0

Кроме того, это скорее проблема «X-Y», просто попытка понять, почему 'getline()' не работает, имеет смысл сейчас. Невозможно представить более подходящий ввод для этого случая. – Inian

2

Если getline является обязательным, вы можете попробовать с do ... while в gawk

awk '!NF{ 
    do getline n; while(length(n)==0); 
    if (match(n, /^\[source/)) print n}' file 

вы получите,

[source,I] 
[source,more] 
[source,1234] 
[source,content] 
+0

Спасибо за предложение. Согласитесь, это дает мне желаемый результат, но я хочу понять, почему моя попытка не читает следующую строку, когда 'NR == 2'! – Inian

+0

@Inian Первая итерация начинается с первой строки, подчиняясь условию '! NF', затем читает n, что пусто, и это не печатает, тогда третья строка не подчиняется условию'! NF' и не вводит block code –

+0

Jose: Моя проблема просто поставлена ​​на 'NR == 2',' getline() 'должен был прочитать следующую строку' [source, I] 'и напечатать ее правильно? Я согласен, что «NR == 3» не выполнил условие '! NF', которое я не сомневаюсь. – Inian

1

@Inian: Конечно же он будет печатать второй номер строки только потому, что GetLine n означает, что курсор переходит к следующей строке из 1-й строки и, очевидно, когда он переходит на вторую строку, тогда, если вы печатаете NR, он будет печатать только строку 2. Итак, когда курсор приходит в первую очередь, он видит NF и входит в него, а затем getline убеждается, что он должен перейти на 2 строки и сохранит его значение n, так что вторая строка тоже пустая, поэтому она напечатает количество строк.

Предложение для кода ИМХО:

awk '!NF{getline n; if (match(n, /^\[source/)) {print n} else {print NR};next} NF' Input_file 

Делая небольшие изменения в ваш код, который вы сможете получить линию 3-го источника, которые тоже не хватало в вас код. Итак, здесь вы проверяете, когда NF NULL, который будет работать, когда 1 пустая и следующая строка источника будет работать, даже если у вас есть n количество пустых строк, а затем строка источника. Поэтому добавление NF в состояние выше и далее в! NF должно также делать трюк.

Вы можете удалить печать NR выше, если это не требуется. Я извиняюсь, если я что-то пропустил, дайте мне знать, если это поможет.

EDIT: Как Инян спросил, почему он терпит неудачу на 2-й линии, позвольте мне попробовать, если я правильно понял проблему и мог бы объяснить здесь.

awk '!NF      ###### !NF, checking that if any line is empty or not, if it is empty then do following. 
{getline n;     ###### getline n, means go to next line(which will be 2nd line now) and have it's value into variable named n. 
if (match(n, /^\[source/)) ###### if n matches the regex pattern then do following, NOTE as n is EMPTY in case of 2nd line is empty, 
             so it will NOT pass the if condition it will go to else and print the line number which is 2. 
{print n} else {print NR}}' ###### printing n in case if condition is TRUE. using else if above condition is NOT true. 
+1

Это не отвечает на мой вопрос! Моя проблема заключается не в том, почему она печатает второй номер строки. Прочтите еще раз. – Inian

+0

Извините, что я пропустил это, если вы хотели объяснить то же самое, ответ Эд Мортон был более ясен, «++» для вашего времени. – Inian

+0

Спасибо Inian, LOVE the candy of ++ :) – RavinderSingh13

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

  • Нет связанных вопросов^_^