Grep / Awk:匹配匹配行上方的shell注释

时间:2016-07-16 20:19:44

标签: awk grep

我有一个像这样的.env文件:

$ cat .env
# My doc for the first var.
FOO_BAR_BAZ1=val1

# My doc for the second var.
# This also spans more than one line.
FOO_BAR_BAZ2=val2

FOO_BAR_BAZ3=val3

当我运行这样的命令时:

$ grep -i "FOO_[^_]*_BAZ*" .env

我希望显示匹配的行,包括前面带有#前缀的行。

知道我怎么能这样做吗?

1 个答案:

答案 0 :(得分:2)

这只打印匹配的行和前面的注释:

awk '/^#/{c = c $0 "\n"; next} /regex_to_match/{print c $0 "\n"} {c=""}' filename

例如:

$ awk '/^#/{c = c $0 "\n"; next} /^FOO_[^_]*_BAZ2/{print c $0 "\n"} {c=""}' .env
# My doc for the second var.
# This also spans more than one line.
FOO_BAR_BAZ2=val2

或:

$ awk '/^#/{c = c $0 "\n"; next} /^FOO_[^_]*_BAZ./{print c $0 "\n"} {c=""}' .env
# My doc for the first var.
FOO_BAR_BAZ1=val1

# My doc for the second var.
# This also spans more than one line.
FOO_BAR_BAZ2=val2

FOO_BAR_BAZ3=val3

如何运作

  • /^#/{c = c $0 "\n"; next}

    如果此行以#开头,则将其添加到带有尾随换行符的字符串变量c。然后跳过其余命令并跳转到next行。

  • /regex_to_match/{print c $0 "\n"}

    如果此行与正则表达式匹配,则打印评论c,当前行$0,并将项目与额外换行符\n分开。如果您不喜欢额外的换行符,可以将其删除。

  • c=""

    如果我们到达这里,那么这一行不是另一个注释行,因此我们到达了注释块的末尾。要准备下一个注释块,c将设置为空字符串。

变异

此版本不区分大小写,并且还允许在脚本的命令行上指定正则表达式:

$ cat script
#!/bin/sh
awk -v x="$1" 'BEGIN{IGNORECASE=1} /^#/{c = c $0 "\n"; next} $0 ~ "^Foo_"x"_" {print c $0 "\n"} {c=""}' .env

作为使用此脚本的示例:

$ sh script 'BA.*'
# My doc for the first var.
FOO_BAR_BAZ1=val1

# My doc for the second var.
# This also spans more than one line.
FOO_BAR_BAZ2=val2

FOO_BAR_BAZ3=val3

Globs与正则表达式

Unix有两种非常不同的表达模式的样式:globs和正则表达式。以globs为例,BAZ*匹配BAZ后跟零个或多个其他任何字符。 Awk不使用globs;它使用正则表达式。在正则表达式中,BAZ*匹配BA后跟零个或多个Z个字符。