我有一个这样的.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
字符。