我正在为nullmailer编写一个小包装器,当我注意到,imho是grep中的一个不需要的行为。 特别是我注意到了@s的一些奇怪。
它会破坏包含@的字符串,并会产生错误的输出。
TL; DR
电子邮件地址有一些规则要遵循(E.G. RFC 2822),所以我会为它们使用故意错误的正则表达式,只是为了让事情变得更短。 请注意,这不会改变我要求的问题。
我在这篇文章中使用的是电子邮件地址,但问题显然是每个字符串中至少有一个@。
我写了一个小脚本来帮助我解释我发现的":
#!/bin/bash
funct1() {
arr=(local1@domain.tld local2@domain.tld)
regex="[[:alnum:]]*@[[:alpha:]]*\.[[:alpha:]]\{2,\}"
for dest in ${arr[@]}; do
printf "%s\n" "$dest" | grep -o -e "$regex"
done
}
funct2() {
arr=(local1@domain.tld local2@domain.tld)
regex="[[:alpha:]]*@[[:alpha:]]*\.[[:alpha:]]\{2,\}"
for dest in ${arr[@]}; do
printf "%s\n" "$dest" | grep -o -e "$regex"
done
}
funct3(){
arr=(local1@dom1@ain.tld local2@dom2@ain.tld)
regex="[[:alpha:]]*@[[:alpha:]]*@[[:alpha:]]*\.[[:alpha:]]\{2,\}"
for dest in ${arr[@]}; do
printf "%s\n" "$dest" | grep -o -e "$regex"
done
}
funct4(){
arr=(local1@dom1@ain.tld local2@dom2@ain.tld)
regex="[[:alpha:]]*@[[:alnum:]]*@[[:alpha:]]*\.[[:alpha:]]\{2,\}"
for dest in ${arr[@]}; do
printf "%s\n" "$dest" | grep -o -e "$regex"
done
}
printf "One @, all parts of regex right:\n"
funct1
printf "One @, first part of regex wrong:\n"
funct2
printf "Two @, first and second part of regex wrong:\n"
funct3
printf "Two @, first part of regex wrong:\n"
funct4
exit 0
为了更好地理解这个问题,我使用了两种类型的字符串:local1@domain.tld
和local1@dom1@ain.tld
,在我看来,grep的行为方式不正确,字符串至少包含@。 / p>
输出结果为:
One @, all parts of regex right:
local1@domain.tld
local2@domain.tld
One @, first part of regex wrong:
@domain.tld
@domain.tld
Two @, first and second part of regex wrong:
Two @, first part of regex wrong:
@dom1@ain.tld
@dom2@ain.tld
funct1
有一个正则表达式可以解决整个字符串,所以没问题,所有字符串都会被打印出来。
funct2
有一个正则表达式,只解决从@到结尾的字符串,所以我应该期待的是没有输出,因为表达式错误;相反,我所拥有的是字符串的第二部分...
这就是为什么我决定在字符串中添加第二个@并进行一些测试。
funct3
只解决从第二个@到最后的字符串,所以我应该期待的是没有输出,因为正则表达式中的错误;好的,没有输出。
funct4
有一个正则表达式,只解决从第一个@到最后的字符串,所以我在这里应该期待的是他不能给我任何东西;相反,我所拥有的是第一个@的输出,就像funct2
一样。
除了funct1
我根本不应该有任何输出,我是对的吗?
为什么grep会在第一个@?
中破坏结果我认为这是一种不受欢迎的行为,因为这样结果将包含在完全不符合我表达式的字符串中。
我错过了什么吗?
编辑:删除标记undefined-behavior
答案 0 :(得分:1)
你的正则表达式有问题,按设计工作。您也可以将@的数量计算为测试。我个人会创建一个这样的布尔方法:
#!/bin/bash
# -- is email address valid ? --
function isEmailValid() {
echo "$1" | egrep -q "^([A-Za-z]+[A-Za-z0-9]*((\.|\-|\_)?[A-Za-z]+[A-Za-z0-9]*){1,})@(([A-Za-z]+[A-Za-z0-9]*)+((\.|\-|\_)?([A-Za-z]+[A-Za-z0-9]*)+){1,})+\.([A-Za-z]{2,})+"
}
if isEmailValid "_#@us@.com" ;then
echo "VALID "
else
echo "INVALID"
fi
if isEmailValid "us@ibm.com" ;then
echo "VALID "
else
echo "INVALID"
fi
或更简单:
function isEmailValid() {
regex="^([A-Za-z]+[A-Za-z0-9]*((\.|\-|\_)?[A-Za-z]+[A-Za-z0-9]*){1,})@(([A-Za-z]+[A-Za-z0-9]*)+((\.|\-|\_)?([A-Za-z]+[A-Za-z0-9]*)+){1,})+\.([A-Za-z]{2,})+"
[[ "${1}" =~ $regex ]]
}