Grep/Awk:匹配行上方的匹配shell注释
我有一个.env文件,如下所示:Grep/Awk:匹配行上方的匹配shell注释,awk,grep,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 当我运行这样的命令时: $ cat .env # My doc for t
$ 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
当我运行这样的命令时:
$ 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
或:
工作原理
如果此行以/^c=c$0”\n;next}
开头,则将其添加到带有尾随换行符的字符串变量#
。然后跳过其余命令并跳到下一行c
如果此行与正则表达式匹配,则打印注释/regex\u to\u 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
全局与正则表达式
Unix有两种非常不同的模式表示方式:全局表达式和正则表达式。例如,对于globs,
BAZ*
匹配BAZ
,后跟零个或多个其他字符。Awk不使用globs;它使用正则表达式。在正则表达式中,BAZ*
匹配BA
,后跟零个或多个Z
字符。这只打印匹配行和前面的注释:
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
或:
工作原理
如果此行以/^c=c$0”\n;next}
开头,则将其添加到带有尾随换行符的字符串变量#
。然后跳过其余命令并跳到下一行c
如果此行与正则表达式匹配,则打印注释/regex\u to\u 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
全局与正则表达式
Unix有两种非常不同的模式表示方式:全局表达式和正则表达式。例如,对于globs,
BAZ*
匹配BAZ
,后跟零个或多个其他字符。Awk不使用globs;它使用正则表达式。在正则表达式中,BAZ*
匹配BA
,后跟零个或多个Z
字符。您可以指定-b1
或-a1
在匹配前后显示一行。如果你想使它更精确,我想你必须使用<代码> SED。我确实考虑了-B和-A选项,但是行的数量有所不同。code>awk是最好的选择。您可以指定-B1
或-A1
在比赛前后显示一行。如果你想使它更精确,我想你必须使用<代码> SED。我确实考虑了-B和-A选项,但是行的数量有所不同。code>awk是个不错的选择。非常有魅力,谢谢。另外,感谢您提供解释。我已对其进行了修改,以适应不区分大小写的匹配awk'BEGIN{IGNORECASE=1}/^#/{c=c$0“\n;next}/^FOO''1''./{print c$0}{c=”“}.env
。但是,将星号(如BA*
)传递到脚本中,然后将其分配给$1
,将产生zsh:no-matches-found:BA*
@Housni非常好。我用一个例子更新了答案,将不区分大小写的命令放在脚本中。如果命令行中有不带引号的glob字符,shell将尝试展开它们。你不会想要这个的。如图所示,将模式放在单引号中,以便将其传递给awk。另外,请注意,awk的模式是正则表达式,而不是全局表达式(请参阅更新的答案)。此外,使用/^FOO''1'''./
可能会有危险:可能会将$1
的内容解释为awk命令,并产生意外后果。答案显示了一种更安全的方法。非常有效,谢谢。另外,感谢您提供解释。我已对其进行了修改,以适应不区分大小写的匹配awk'BEGIN{IGNORECASE=1}/^#/{c=c$0“\n;next}/^FOO''1''./{print c$0}{c=”“}.env
。但是,将星号(如BA*
)传递到脚本中,然后将其分配给$1
,将产生zsh:no-matches-found:BA*
@Housni非常好。我用一个例子更新了答案,将不区分大小写的命令放在脚本中。如果命令行中有不带引号的glob字符,shell将尝试展开它们。你不会想要这个的。如图所示,将模式放在单引号中,以便将其传递给awk。另外,请注意,awk的模式是正则表达式,而不是全局表达式(请参阅更新的答案)。此外,使用/^FOO''1'''./
可能会有危险:可能会将$1
的内容解释为awk命令,并产生意外后果。答案显示了一种更安全的方法。