Как я могу обработать многострочные записи с помощью awk в bash-скрипте?

13

Пример.txt ниже

Restaurant: McDonalds 
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

Restaurant: 5 guys
City: Atlanta
State: Georgia
Address: 123 Peachtree Rd
Phone: 911

Restaurant: KFC
City: NYC
State: NY
Address: 123 Madison Square
Phone: 911

Я использую скрипт bash и, скажем, я хочу найти ресторан по его названию из файла выше. Попросите пользователя ввести название ресторана, и он должен напечатать информацию об этом ресторане (5 строк).

awk '/McDonalds/> /KFC/' example.txt

Я знаю, что строка кода выше будет печатать всю строку, которая соответствует шаблону «McDonalds» и «KFC», но это будет просто печатать 1-ю строку из текстового файла, но не остальную информацию об этом ресторане. Как я могу сказать ему распечатать всю информацию (5 строк) только из пользовательского ввода названия ресторана?

Селена Гомез
источник

Ответы:

11

С помощью awk вы можете изменить разделитель записей . По умолчанию это новая строка, поэтому каждая строка файла является записью. Если вы установите RSпеременную в пустую строку, awk будет считать записи разделенными пустыми строками:

awk -v name="KFC" -v RS="" '$0 ~ "Restaurant: " name' example.txt
Гленн Джекман
источник
Я не понимаю твой вопрос. Это довольно расплывчато. Это назначение или использование, которое вы не получаете?
Гленн Джекман
3

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

$ sed -n '/KFC/,/^$/p' file
Restaurant: KFC
City: NYC
State: NY
Address: 123 Madison Square
Phone: 911

$ sed -n '/McDo/,/^$/p' file
Restaurant: McDonalds
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

объяснение

Это основная sedфункция, вы можете сослаться на ПОЛЕЗНЫЕ ОДНО-ЛИНИЙНЫЕ СКРИПТЫ ДЛЯ САС

# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p'             # case sensitive
BMW
источник
Добавьте объяснение.
BMW
Но почему предложенное редактирование отклонено? Я не изменил ответ. Я только что улучшил форматирование.
маргаритка
2
$ awk '$2=="KFC" {print; for(i=1; i<=4; i++) { getline; print}}' example.txt

Restaurant: KFC
City: NYC
State: NY
Address: 123 Madison Square
Phone: 911

Приведенная выше команда получит и напечатает 4 последовательные строки вместе с текущей строкой, поскольку она была передана в цикл for. Шаблон поиска $2=="KFC"поможет получить определенную строку из нескольких строк.

Авинаш Радж
источник
0

Другое возможное решение:

awk 'BEGIN{FS="\n";RS="\n\n"}{if($1=="KFC")print $0}' example.txt
Фейсал
источник
{if($1=="KFC")print $0}Может конденсироваться просто $1 == "KFC", так как действие по умолчанию для истинного состояния является печать записи.
Муру
0

Достаточно напечатать от строки, содержащей желаемое имя, до последней строки, содержащей слово Phone(при условии, конечно, что все записи следуют одному и тому же шаблону и всегда будут иметь Phoneзавершающую запись)

$> awk '/5 guys/,/Phone/' restaurants.txt                                     
Restaurant: 5 guys
City: Atlanta
State: Georgia
Address: 123 Peachtree Rd
Phone: 911
$> awk '/McDonalds/,/Phone/' restaurants.txt                                  
Restaurant: McDonalds 
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

Если мы хотим немного усложнить это, мы можем напечатать ровно 5 строк после матча, например:

awk '/McDonalds/{stop=NR+5}; NR<=stop ' restaurants.txt                    

Restaurant: McDonalds 
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

stopПеременная не будет установлена, так что NR<=stopничего не будет печатать, пока /McDonalds/{stop=NR+5;}часть фактически не устанавливает переменную, и что будет происходить только тогда , когда мы находим матч.

Сергей Колодяжный
источник