变量为空时不匹配正则表达式

时间:2021-05-24 16:23:27

标签: bash shell awk grep

我有以下文件

more /etc/hosts
23.1.22.162 kafka01.dfg.com
23.1.22.155 kafka02.dfg.com
23.1.22.222 kafka03.dfg.com
23.1.22.111 master01.dfg.com
23.1.22.239 master02.dfg.com
23.1.22.170 master03.dfg.com
23.1.22.167 worker01.dfg.com
23.1.22.165 worker02.dfg.com
23.1.22.112 worker03.dfg.com

我们想在 masterworker 时捕获所有 kafka_name=""egrep 机器,所以我们这样做了

kafka_name=""
egrep "\smaster|\sworker|\s$kafka_name"  /etc/hosts

但我们仍然得到主机包括 kafka 机器

 egrep "\smaster|\sworker|\s$kafka_name"  /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
23.1.22.162 kafka01.dfg.com
23.1.22.155 kafka02.dfg.com
23.1.22.222 kafka03.dfg.com
23.1.22.111 master01.dfg.com
23.1.22.239 master02.dfg.com
23.1.22.170 master03.dfg.com
23.1.22.167 worker01.dfg.com
23.1.22.165 worker02.dfg.com
23.1.22.112 worker03.dfg.com

无论如何当我们设置

kafka_name="kafka"

我们也得到了 kafka 机器

egrep "\smaster|\sworker|\s$kafka_name"  /etc/hosts
23.1.22.162 kafka01.dfg.com
23.1.22.155 kafka02.dfg.com
23.1.22.222 kafka03.dfg.com
23.1.22.111 master01.dfg.com
23.1.22.239 master02.dfg.com
23.1.22.170 master03.dfg.com
23.1.22.167 worker01.dfg.com
23.1.22.165 worker02.dfg.com
23.1.22.112 worker03.dfg.com

那为什么当我们设置

kafka_name=""

尽管 $kafka_name 为空,它是否仍然从主机打印 kafka 机器?

2 个答案:

答案 0 :(得分:3)

仅供参考 egrep 已弃用,而支持 grep -E

不过,请考虑使用 awk,以便对您想要表达的任何条件(不仅仅是正则表达式 - 条件)进行清晰、简单的控制,例如:

$ kafka_name=''
$ awk -v kafka_name="$kafka_name" '( $2 ~ /^(master|worker)/ ) || ( (kafka_name != "") && ($2 ~ ("^"kafka_name)) )' file
23.1.22.111 master01.dfg.com
23.1.22.239 master02.dfg.com
23.1.22.170 master03.dfg.com
23.1.22.167 worker01.dfg.com
23.1.22.165 worker02.dfg.com
23.1.22.112 worker03.dfg.com

$ kafka_name='kafka02'
$ awk -v kafka_name="$kafka_name" '( $2 ~ /^(master|worker)/ ) || ( (kafka_name != "") && ($2 ~ ("^"kafka_name)) )' file
23.1.22.155 kafka02.dfg.com
23.1.22.111 master01.dfg.com
23.1.22.239 master02.dfg.com
23.1.22.170 master03.dfg.com
23.1.22.167 worker01.dfg.com
23.1.22.165 worker02.dfg.com
23.1.22.112 worker03.dfg.com

以上代码可以在任何 Unix 机器上的任何 shell 中使用任何 awk。

它使用正则表达式而不是字符串比较,就像在您的 egrep 命令中所做的那样,因此如果这些名称中的任何一个可以包含正则表达式元字符,您需要将它们转义或将脚本更改为在任何地方使用 index($2,string) == 1 而不是 $2 ~ /^regexp/,例如:

$ awk -v kafka_name="$kafka_name" '(index($2,"master") == 1) || (index($2,"worker") == 1) || ( (kafka_name != "") && (index($2,kafka_name) == 1) )' file
23.1.22.155 kafka02.dfg.com
23.1.22.111 master01.dfg.com
23.1.22.239 master02.dfg.com
23.1.22.170 master03.dfg.com
23.1.22.167 worker01.dfg.com
23.1.22.165 worker02.dfg.com
23.1.22.112 worker03.dfg.com

答案 1 :(得分:2)

$kafka_name 为空时,模式为 "\smaster|\sworker|\s",最后一个选项匹配任何有空格的行,所以它匹配所有内容。

一种选择是将 $kafka_name 设置为您知道永远不会存在的内容而不是空字符串,例如

kafka_name=kafkaXXXX

另一种方法是仅当模式不为空时才将 $kafka_name 添加到模式中。

pattern="\smaster|\sworker"
if [ -n "$kafka_name" ]
then pattern="$pattern|\s$kafka_name"
fi
egrep "$pattern" /etc/hosts