Jak mogę przetwarzać rekordy wieloliniowe za pomocą awk w skrypcie bash?


14

example.txt jest poniżej

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

Używam skryptu bash i powiedzmy, że chcę wyszukać restaurację według jej nazwy z powyższego pliku. Poproś użytkownika o podanie nazwy restauracji, a powinna wydrukować informacje dotyczące tej restauracji (5 wierszy).

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

Wiem, że powyższy wiersz kodu wydrukuje całą linię pasującą do wzorca „McDonalds” i „KFC”, ale to po prostu wydrukuje pierwszy wiersz z pliku tekstowego, ale nie resztę informacji o tej restauracji. Jak mogę nakazać wydrukowanie wszystkich informacji (5 linii) z samego wpisu nazwy restauracji?

Odpowiedzi:


11

Za pomocą awk możesz zmienić separator rekordów . Domyślnie jest to nowa linia, więc każda linia pliku jest rekordem. Jeśli ustawisz RSzmienną na pusty ciąg znaków, awk rozważy rekordy jako oddzielone pustymi wierszami:

awk -v name="KFC" -v RS="" '$0 ~ "Restaurant: " name' example.txt

Nie rozumiem twojego pytania. To jest dość niejasne. Czy to zadanie, którego nie używasz?
glenn jackman

3

Używanie 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

Wyjaśnienie

Jest to podstawowa sedfunkcja, możesz odnieść PRZYDATNE SKRZYDŁA W JEDNEJ LINII DO SED

# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p'             # case sensitive

Dodaj wyjaśnienie.
BMW

Ale dlaczego sugerowana edycja została odrzucona? Nie zmieniłem odpowiedzi. Właśnie poprawiłem formatowanie.
stokrotka

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

Powyższe polecenie pobierze i wydrukuje kolejne 4 linie wraz z bieżącą linią, ponieważ zostało wprowadzone do pętli for. Wzorzec wyszukiwania $2=="KFC"pomoże uzyskać konkretną linię z wielu linii.


0

Inne możliwe rozwiązanie:

awk 'BEGIN{FS="\n";RS="\n\n"}{if($1=="KFC")print $0}' example.txt

{if($1=="KFC")print $0}Można kondensować się po prostu $1 == "KFC", ponieważ domyślna akcja dla prawdziwego stanu jest, aby wydrukować zapis.
mur 12.04.16

0

Wystarczy wydrukować z wiersza zawierającego żądaną nazwę, aż do ostatniego wiersza zawierającego słowo Phone(zakładając oczywiście, że wszystkie wpisy mają ten sam wzór i zawsze będą miały Phonezapis kończący)

$> 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

Gdybyśmy chcieli trochę to skomplikować, moglibyśmy wydrukować dokładnie 5 linii po meczu, w ten sposób:

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

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

stopZmienna nie zostanie ustawiona, więc NR<=stopnie będzie niczego drukować, aż /McDonalds/{stop=NR+5;}część faktycznie ustawia zmienną, a to nastąpi tylko wtedy, gdy znajdziemy mecz.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.