2013-06-10 2 views
4

У меня есть файл со структуройход линии, которая соответствует шаблону к предыдущей строке

12312 
desc: bleh... 
9938 
desc: blah... 
desc: bloh... 
desc: blih... 
desc: bluh... 
9912 
desc: blah... 

и я хочу, чтобы переместить линию, которая соответствует шаблону «DESC:» к предыдущей строке или удалить «\ п» в строке, которая идет перед каждым шаблоном «desc:».

желаемый результат:

12312 desc: bleh... 
9938 desc: blah... desc: bloh... desc: blih... desc: bluh... 
9912 desc: blah... 

Я попытался

awk '!/desc:/{ 
printf "%s ",$0 
getline 
printf "%s \n",$0 
} 
/desc/{print}' file 

без результата.

Фактически все данные являются выходными данными awk -F\" '{print $4 "\t" $6}' Возможно, я могу что-то сделать в первую очередь?

+0

Не могу получить: 'desc: blah ...' не соответствует '9912', но он движется к нему. Вы можете уточнить свой вопрос? – PoGibas

+0

Я хочу переместить строку, которая соответствует шаблону «desc:» в предыдущую строку или удалить «\ n» в строке, которая идет перед каждым шаблоном «desc:». –

+0

Использование getline - это, как правило, неправильный подход, и это, безусловно, в этом случае. Даже не думайте об использовании getline, пока не прочитаете http://awk.info/?tip/getline и ПОЛНОСТЬЮ не поймете все оговорки. –

ответ

12

Один из способов с awk:

$ awk '!/^desc:/&&NR>1{print OFS}{printf "%s ",$0}END{print OFS}' file 
12312 desc: bleh... 
9938 desc: blah... desc: bloh... desc: blih... desc: bluh... 
9912 desc: blah... 

Объяснение:

  • !/^desc:/ матч линии, которые не начинаются с desc: не включая первую строку в файле NR>1.
  • {print OFS} распечатать разделитель выходного поля перед совпадающей строкой. В awk по умолчанию OFS - \n.
  • {printf "%s ",$0} печатать каждую строку без задней строки новой строки.
  • END{print OFS} после того, как файл был прочитан, добавьте завершающую новую строку.

Живая демонстрация: http://ideone.com/ajH14u решение

+0

не могу у объясните пожалуйста. Я не получаю такого же результата. на самом деле все данные - это вывод 'awk -F \ '' {print $ 4" \ t "$ 6} '' –

+0

@IgorVoltaic. Я добавил объяснение. Неважно, где данные поступали с тех пор, пока они находятся в формат, описанный в вопросе, который будет работать. Говорить, что вы не получаете одинаковые результаты, не помогает. –

+3

'END {print OFS}' добавит пробел в конец каждой строки, используйте 'END {print" " } 'только для печати новой строки. Вы также добавляете второй пробел в конец каждой строки, используя' printf '% s', $ 0' вместо 'printf '% s', $ 0', но вам нужно будет переосмыслить логику сценария, чтобы решить эту проблему. –

3

Perl:

perl -pe 's/\n/ /; ! /^desc:/ and print "\n" unless 1 == $.' FILE 
+1

Не было бы более интуитивно понятным с 'print '\ n", если только 1 == $. ||/^ desc:/'? – doubleDown

+0

Я предполагаю'!/^ desc:/and print «\ n», если 1 == $ .' означает 'если desc не найден, напечатайте новую строку, если в строке не существует только одного поля. Это довольно неприятное высказывание по соображениям, поскольку в нем есть как минимум пара негативов , Разве нет более четкого способа написать это? Я вижу предложение «print» \ n ", если только 1 == $. ||/^ desc:/'в комментарии, но вы не можете просто написать что-то четкое и простое, например' if ($.> 1 ||/^ desc: /) напечатать "\ n" 'в perl? Я даже не знаю, правильно ли это интерпретирует первоначальное намерение perl. –

+0

Ну, это демонстрирует, как я туда попал: я начал с 'и', заметил пустую строку в начале, поэтому добавил' except'. – choroba

11

sed Oneliner

sed ':a $!N;s/\ndesc/ desc/;ta P;D' 

Выведет

12312 desc: bleh... 
9938 desc: blah... desc: bloh... desc: blih... desc: bluh... 
9912 desc: blah... 
+0

отлично, спасибо! –

+1

Не благодарите, отметьте как ответ;): D – bartimar

1

Использование

содержания script.vim:

set backup 
g/\v^desc/ normal kJ 
saveas! output.txt 
q! 

Выполнить это нравится:

vim -u NONE -N -S script.vim infile 

И это создаст output.txt файл с содержимым:

12312 desc: bleh... 
9938 desc: blah... desc: bloh... desc: blih... desc: bluh... 
9912 desc: blah... 
4
$ cat file 
12312 
desc: bleh... 
9938 
desc: blah... 
desc: bloh... 
desc: blih... 
desc: bluh... 
9912 
desc: blah... 

$ awk '{printf "%s%s",(/^desc:/?OFS:ors),$0; ors=ORS} END{print ""}' file 
12312 desc: bleh... 
9938 desc: blah... desc: bloh... desc: blih... desc: bluh... 
9912 desc: blah... 
+1

+1 Никогда не видел такой реализации 'printf'. –

+1

@Jaypal - это обычный способ awk иметь дело с соединительными линиями. Вам либо нужно распечатать ORS (или ничего, если это первая строка на входе), либо OFS перед каждой строкой на основе, если это первая строка в блоке или последующей строке, поэтому вы просто используете трехмерное выражение для фиксации условия который отличает первый от последующих строк в блоке. –

+0

Правда, это просто использование «тернарного оператора» внутри 'printf' отлично. –

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