如何将包含双引号和单引号的正则表达式正确打包到变量中并在 Bash 中对其求值?

如何将包含双引号和单引号的正则表达式正确打包到变量中并在 Bash 中对其求值?

stackoverflow 问题给出了以下用于符合 RFC5322 的电子邮件格式匹配的正则表达式:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

正则表达式包含必须匹配的单引号和双引号。

将其存储到变量中然后对其求值的正确、可移植的 Bash 方法是什么?

我的方法是使用单引号,然后在正则表达式的每个单引号之前结束单引号部分,添加转义单引号,然后继续使用单引号其余部分,这将导致以下结果(请注意将'原始正则表达式中的所有内容替换为并在完整正则表达式的开头和结尾处'\''添加一个:'

regex='(?:[a-z0-9!#$%&'\''*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'\''*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])'

然后输入echo $regex(以及echo "$regex$")将完全按照原始链接中的定义输出正则表达式字符串。然后,对其进行评估:

if [[ "$email" =~ $regex ]] ; then
    echo "This is an RFC5322 compliant e-mail address"
else
    echo "This is NOT an RFC5322 compliant e-mail address"
fi

但是,仅使用普通电子邮件地址进行测试会失败(如果使用也会失败)email="[email protected]"if [[ "$email" =~ "$regex" ]] ; then

有什么问题以及在 bash 中执行此操作的最佳/最干净的方法是什么? (如果有人会说不要使用 bash,不幸的是这是一个先决条件,RFC5322 一致性也是如此)

答案1

perl这就是您使用in进行操作的方式bash

  • 将正则表达式放在 Perl 的环境托盘上。
  • 通过管道将电子邮件地址传输到 Perl 的标准输入上。
  • 然后尝试在 perl 中匹配并以相反的状态退出,因为 bash 和 perl 具有互补的成功感。
  • 休息是你的事情。
printf '%s\n' "$email" \
| _regex_="$regex"     \
     perl -0777 -ne 'chop;exit !/$ENV{_regex_}/'

if [[ $? == 0 ]] ; then
    echo "This is an RFC5322 compliant e-mail address"
else
    echo "This is NOT an RFC5322 compliant e-mail address"
fi

相关内容