Awk 多行匹配,打印输出用换行符分隔

Awk multiline match, print output separated by newline

提问人:larryTheLamb 提问时间:8/12/2023 最后编辑:larryTheLamb 更新时间:8/13/2023 访问量:79

问:

我正在遵循示例如何在 bash 脚本中使用 awk 处理多行记录

我的输入是:

Restaurant: Chik-Fil-A 
City: Columbus
State: GA
Address: 123 Biscayne Blvd
Phone: 911

Restaurant: 5 guys
City: Columbus
State: GA
Address: 123 Peachtree Rd
Phone: 911

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

Restaurant: Bahama Breeze
City: Orlando
State: FL
Address: 123 Madison Square
Phone: 911

我想选择哥伦布的所有餐厅:

awk -v name="Columbus" -v RS="" '$0 ~ "City: " name' file.txt

我的输出是这样的:

Restaurant: Chik-Fil-A 
City: Columbus
State: GA
Address: 123 Biscayne Blvd
Phone: 911
Restaurant: 5 guys
City: Columbus
State: GA
Address: 123 Peachtree Rd
Phone: 911

我想要的是这个:

Restaurant: Chik-Fil-A 
City: Columbus
State: GA
Address: 123 Biscayne Blvd
Phone: 911

Restaurant: 5 guys
City: Columbus
State: GA
Address: 123 Peachtree Rd
Phone: 911

我希望每个输出记录都用换行符分隔。我试过玩 FS 和 ORS,但我一直得到相同的结果。我真的很感激任何帮助。

谢谢

AWK 多行

评论

3赞 Paolo 8/12/2023
怎么样 ?ORS=\n\n
0赞 larryTheLamb 8/12/2023
太棒了!谢谢!我一直在尝试 ORS=“\n”。出于兴趣,为什么我需要额外的 NL?
1赞 Paolo 8/12/2023
默认值为单个换行符,但由于需要两个换行符,因此必须添加另一个换行符ORS
0赞 Ed Morton 8/12/2023
$0 ~ "City: " name如果输入文件中存在 is 和 town of ,则将产生假匹配。您应该改用。如果你关心城镇名称中可能的(或任何其他正则表达式元字符)也会产生错误的匹配,那么添加任何对你有意义的变体。nameLondonLondonderry$0 ~ ("(^|\n)City: " name "(\n|$)").BEGIN{ gsub(/[.]/,"[&]",name) }

答:

3赞 Paolo 8/12/2023 #1

您可以设置为两个换行符以获得所需的输出:ORS

awk -v name="Columbus" -v ORS="\n\n" -v RS="" '$0 ~ "City: " name' file.txt
3赞 RavinderSingh13 8/13/2023 #2

对于使用带有正则表达式的函数的示例,请尝试以下代码。matchawk

awk -v name="Columbus" -v ORS="\n\n" -v RS="" '
match($0,"\nCity: " name"\n")
' Input_file

评论

1赞 David C. Rankin 8/13/2023
很好地使用 作为伪锚来解决 Ed 的担忧。'\n'
1赞 RavinderSingh13 8/13/2023
@DavidC.Rankin,谢谢你,先生。
1赞 The fourth bird 8/18/2023
我从来不知道这意味着段落模式,非常聪明的匹配。RS=""
1赞 RavinderSingh13 8/18/2023
@Thefourthbird,谢谢你,先生。
1赞 Renaud Pacalet 8/13/2023 #3

比 或 更安全一点,特别是如果你的字符可能会被解释为正则表达式运算符(句点、星号、方括号......~matchname

awk -v name="Columbus" -v RS="" -v ORS='\n\n' '
  {c=$0; sub(/.*\nCity: */,"",c); sub(/\n.*/,"",c)} c==name' file.txt

(用于仅保留城市名称并比较相等,而不是正则表达式匹配)。subc

请注意,如果您的城市名称不能包含正则表达式运算符,则提供更简单的解决方案:grep

name=Columbus
grep "^City:[[:space:]]\+$name\$" -A4 -B1 file.txt