2016-04-29 4 views
0

У меня есть список, как это:Как выполнить поиск первого совпадения второго ключевого слова перед совпадением первого ключевого слова с помощью awk или grep?

TAGDESCRIPTIONS example 
TAGS   tmp 
TAGS   line 
TAGDESCRIPTIONS bar 
TAGS   com      
TAGS   foo  

Что такое право команды в AWK или Grep, чтобы он соответствовать TAGDESCRIPTIONS линии после получения спички foo? Поэтому при поиске foo он печатает bar.

ответ

1

Grep не подходит для этого, поскольку это в основном для фильтрации определенных линий, но вы спросите об отношениях в различных линиях. Греп может быть принужден к выполнению вещей на нескольких строках по (ab) с использованием флага -z, который ожидает нулевых байт разделенных строк, но обычно это не очень.

Awk позволяет простое решение:

$ awk 'BEGIN{RS="TAGDESCRIPTIONS"}/foo/{print $1}' infile 
bar 

Это устанавливает разделитель записей RS к TAGDESCRIPTIONS, так что вход интерпретируется как три записи (\n обозначает символ новой строки):

<empty record> 
example\nTAGS   tmp\nTAGS   line\n 
bar\nTAGS   com\nTAGS   foo\n 

Первый пуст, потому что файл начинается с разделителя записей.

Для каждой записи то, что у нас есть до первой новой строки, является описанием тега. Что мы говорим с

/foo/{print $1} 

заключается в следующем: если запись соответствует foo, печати первого поля записи (описание).

Это совсем не бомбоубежище. Если описание состоит из нескольких слов, оно печатает только первое. Если описание вместо тега совпадает, оно ложно. Если запись содержит foobar, но не bar, она по-прежнему будет соответствовать.

Этот вход примера скиньте простое решение:

TAGDESCRIPTIONS foo 
TAGS   blah 
TAGDESCRIPTIONS example 
TAGS   tmp 
TAGS   line 
TAGS   foobar 
TAGS   barfoo 
TAGDESCRIPTIONS bar and more words 
TAGS   com 
TAGS   foo 

Существует описание тегов с foo теги , содержащихfoo и описание тегов с несколькими словами.

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

awk ' 
BEGIN { RS = "TAGDESCRIPTIONS *" } 

{ 
    # Split record at newlines, store in arr 
    split($0, arr, "\n") 

    # Skip first element (description), compare to 'foo' 
    for (i = 2; i <= length(arr); ++i) { 
     if (arr[i] ~ " +foo$") { 

      # Matches - print description 
      print arr[1] 

      # No need to look at the rest of the record 
      break 
     } 
    } 
}' infile 

в результате

bar and more words 

GNU awk, если быть точным, из-за разделителя записей с несколькими символами и функции length.

+1

Следует упомянуть о специфике gawk из-за многосимвольного RS и 'length (array)'. –

0

Я сделаю снимок.
Я не знаю grep или awk, но ниже это просто необработанное регулярное выражение
, в котором используется внешний вид PCRE и встроенная группа модификаторов.

(?ms)^TAGDESCRIPTIONS\s+(\w*)\s+(?:(?!^TAGDESCRIPTIONS).)+^TAGS\s+foo

Expanded

(?ms) 
^ TAGDESCRIPTIONS \s+ 
(\w*)      # (1) 
\s+ 
(?: 
     (?!^TAGDESCRIPTIONS) 
     . 
)+ 
^ TAGS \s+ foo 

bar слово в группе захвата 1. Плоть из регулярных выражений, как вам нужно.

Выход

** Grp 0 - (pos 68 , len 83) 
TAGDESCRIPTIONS bar 
TAGS   com      
TAGS   foo 
** Grp 1 - (pos 84 , len 3) 
bar 
2
$ awk '/TAGDESCRIPTIONS/{d=$2} /foo/{print d}' file 
bar 

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

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