如何在 bash 脚本中使用 awk 处理多行记录?

如何在 bash 脚本中使用 awk 处理多行记录?

example.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”匹配的整行,但那只会打印文本文件的第一行,而不会打印有关该餐厅的其余信息。我怎样才能让它仅根据用户输入的餐厅名称打印所有信息(5 行)?

答案1

使用 awk,你可以更改记录分隔符。默认情况下,它是换行符,因此文件的每一行都是一条记录。如果将变量设置RS为空字符串,awk 将认为记录由空行分隔:

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

答案2

使用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功能,你可以参考有用的 SED 单行脚本

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

答案3

$ 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"将有助于从多行中获取特定行。

答案4

从包含所需名称的行打印到包含单词的最后一行就足够了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;}部分实际设置该变量,而这只会在我们找到匹配时才会发生。

相关内容