2013-03-30 5 views
4

У меня есть файл структурированную так:Как grep по разделам?

BOF 

-------Title1------- 
stuff here 
some stuff 

-------Title2------- 
extra things 
extra things 
extra things 

-------Title3------- 
and some stuff 
    here 

... 

-------Title4------- 
stuff 

EOF 

Теперь я хотел бы сделать что-то вроде этого:

grep-by-section KEYWORD DELIMITER my-file 

так что

grep-by-section "some" "^---" my-file 

выходы

-------Title1------- 
stuff here 
some stuff 

-------Title3------- 
and some stuff 
    here 

Я хочу найти определенное ключевое слово и для каждого поиска, я хочу вывести весь блок между известными разделителями. Как я могу это сделать? sed не может меня здесь.

Разделители здесь являются «------», но могут быть чем-то вроде чисел в формате [0-9] {8}, например.

Подобная проблема, которую я не мог решить, вместо вывода содержимого блока выводит только заголовок блока.

Казалось бы, проще решать с perl чем sed

+0

Я думаю, что 'awk' будет хорошим решением. См. [Эту тему] (http://stackoverflow.com/questions/15628017/) для аналогичной ситуации. – rojo

ответ

4
#!/usr/bin/perl 
my ($search, $del) = splice(@ARGV, 0, 2); 
local $/; 
while (<>) { 
    for (/($del(?:(?!$del).)*)/smg) { 
     print if /$search/sm; 
    } 
} 

Примечание:

  • local $/ вызывает следующее Readline для чтения файла в то время, вместо строки в то время.
  • (?:(?!STRING).)* - STRING как [^CHAR]* - CHAR.
+0

Ничего себе. Это потрясающе, но можете ли вы сделать его более читаемым для нас смертных? ;) (Привет ikegami!) – Jess

+1

Документировал сложные детали. – ikegami

0

Если есть истинные пустые строки между этими записями, вам не нужно будет использовать эти разделители, это будет достаточно:

awk '/KEYWORD/' RS= ORS='\n\n' file 

В противном случае вы можете попробовать этот AWK:

awk ' 
    $0~key{ 
    f=1 
    } 
    $0~del{ 
    if(f)print s 
    f=0 
    s=$0 
    next 
    } 
    { 
    s=s RS $0 
    } 
    END{ 
    if(f)print s 
    } 
' key="KEYWORD" del="DELIMITER" file 

В одной строке:

awk '$0~key{f=1} $0~del{ if(f)print s ; f=0; s=$0; next } {s=s RS $0} END{ if(f)print s }' key="KEYWORD" del="DELIMITER" file 
Смежные вопросы