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

  • 本文关键字:外壳 注释 Grep Awk 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

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

知道我该怎么做吗?

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

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和正则表达式。 例如,对于 glob,BAZ*匹配BAZ后跟零个或多个任何其他字符。 Awk 不使用球体;它使用正则表达式。 在正则表达式中,BAZ*匹配项BA后跟零个或多个Z字符。

最新更新