Regex 我可以将正则表达式的求值存储到变量中吗?

Regex 我可以将正则表达式的求值存储到变量中吗?,regex,bash,Regex,Bash,我收到一个字符串,该字符串可以是全数字破折号分隔的,在这种情况下,它对我来说是可接受的(例如123423-56788-456522-34245),也可以不是全数字且仍然是破折号分隔的,在这种情况下,它对我来说是不可接受的(例如123423-56788-shelve-34245) 为了确定字符串是否可接受,我构建了以下if块: REGEX_FOR_ONLY_NUMERICAL_CHANGELISTS='^[0-9-]+$' if [[ ${BUILD_ID} =~ ${REGEX_FOR_ONLY

我收到一个字符串,该字符串可以是全数字破折号分隔的,在这种情况下,它对我来说是可接受的(例如
123423-56788-456522-34245
),也可以不是全数字且仍然是破折号分隔的,在这种情况下,它对我来说是不可接受的(例如
123423-56788-shelve-34245

为了确定字符串是否可接受,我构建了以下if块:

REGEX_FOR_ONLY_NUMERICAL_CHANGELISTS='^[0-9-]+$'
if [[ ${BUILD_ID} =~ ${REGEX_FOR_ONLY_NUMERICAL_CHANGELISTS} ]]
then
    echo true
else
    echo false
fi 
上面的if块工作正常。但是,如果我要用另一种语言(例如Java)编程,我会直接将求值赋值到变量中。例如:

int a = 3; 
int b = 5; 
boolean test = (a < b);
。。。这两个变量分别假定值
0
1
。这不完全是真或假,但我仍然可以接受。 但是,我似乎无法对我的表达式进行同样的处理,因为如果我这样做:

bash$ false_expression=$((2 == 4))
bash$ true_expression=$((2 == 2))
InvalidCL=123423-56788-shelve-34245
MyRegex='^[0-9-]+$'
FalseExpression=$((${InvalidCL} =~ ${MyRegex}))
…第三个赋值引发此错误:

-bash: 123423-56788-shelve-34245 =~ ^[0-9-]+$: attempted assignment to non-variable (error token is "=~ ^[0-9-]+$")

我不是一个真正的bash专家,所以我的问题(希望不是太傻)是:是否可以将求值赋值给一个变量?如果[[myExpression]]的计算结果为
true
,我可以看到我的
,所以我不明白为什么我不能将此计算结果分配给变量。。。有人能解释一下吗?

如果你真的想用一个作业来完成,那么你可以这样做:

FalseExpression=$( [[ "$InvalidCL" =~ $MyRegex ]] && echo 1 || echo 0)
其中,
1
代表
true
0
代表
false
。但是请记住,这不是传统的Bash方式。Bash中
0
的结果表示没有错误,即,如果表达式的计算结果为
true
,则您将获得以下退出状态:

$ echo $?
0
请注意,使用single
表示命令替换,而示例中的
表示数学表达式

传统上,人们可能会这样做:

$ [[ "$InvalidCL" =~ $MyRegex ]]
$ FalseExpression=$?
Bash将最后一个操作的退出状态存储在“$?”中,其行为方式与
$(())
运算符相反。如果表达式为
true
,则
$?
将存储
0
,而$(())将返回
1
。如果您来自C语言背景,后者可能更为常见。我建议不要混合使用这些方法。如果一个结果可能具有不同的含义,则调试脚本可能会非常困难。

您还可以执行以下操作:

[[ ${BUILD_ID} =~ ${REGEX_FOR_ONLY_NUMERICAL_CHANGELISTS} ]]
val=$?

避免调用子shell。同样,成功时val为0,失败时val为1。

如果您希望直接将单行赋值给数值布尔值,可以在测试中使用“not”运算符

强烈建议您对此添加一些解释性意见

为了更清晰,制作一个包含注释的函数来封装逻辑,并从一行调用它

boolMatch() { 
   local match str="$1" pat="$2"

   # test the match
   [[ "$str" =~ $pat ]]

   # invert the return to a boolean value
   match=$(( ! $? ))

   # pass back the boolean
   echo $match
}

$: boolMatch foo bar
0
$: boolMatch foo foo
1
$: match=$( boolMatch $stringToCheck $patternToUse )

其他人已经指出了如何获得正则表达式匹配的布尔返回值

关于实际问题的措辞,我想指出,regex表达式的计算结果实际上自动存储在bash中的一个环境变量中。
$bash\u REMATCH
数组将整个匹配存储在索引
0
处,并将捕获组存储在各自的索引处。请参阅:

此数组中的元素数也可以用作匹配成功的指示器,这可能比
$?
中的手动赋值更方便。如果
${BASH\u REMATCH[*]}
为零,则最后一个正则表达式不匹配


您会收到所引用的错误消息,因为正则表达式匹配语法仅在
[…]
构造中定义,而不是在
$(…)
算术求值中定义,因此当它看到
=
时,它认为您必须尝试某种赋值。

不需要
&
|
;只要
$([…];echo$?)
就足够了。@chepner是的,但是OP发布了:
true\u expression=$((2==2))
,我从中得出结论,他想要一个
1
来表示
true
,因此条件运算符分配“正确的”值。很好。这取决于使用
FalseExpression
的上下文。谢谢你的回答。我喜欢这种方法,但如果我定义
ValidCL=123423-56788-456522-34245
然后运行
TrueExpression=$([[$ValidCL=~$MyRegex]]和&echo 1 | | echo 0)
TrueExpression
的值仍然是
0
,而它应该是
1
。与您展示的第二个解决方案相同:(P.s.我澄清:无论表达式是真是假,它都会打印相同的结果。这不是切换0和1的问题(我知道我们正在跟踪成功-0-或失败-1).
val=$?
Bash在
=
之前和之后都不允许有空格。正如对Paul的答案的评论,即使你的作品也很好,但我发现对于第一个阅读代码的人来说,理解起来有点困难。在接受答案之前,我会等待一段时间,看看其他答案是否显示出更清晰的解决方案,但a+1是值得的:)这很好。但是,正如您所说,对于代码的第一个读者来说,这有点难理解。在接受答案之前,我会等一等,看看其他答案是否显示出更清晰的解决方案,但a+1是值得的:)还有几分钟,所以我扩展了我的答案。:)谢谢Paul,非常感谢。我将使用另一个答案,因为我发现其他人触摸代码时更容易阅读,但这也很好,谢谢!这是我开始的第一个实际答案。:D
boolMatch() { 
   local match str="$1" pat="$2"

   # test the match
   [[ "$str" =~ $pat ]]

   # invert the return to a boolean value
   match=$(( ! $? ))

   # pass back the boolean
   echo $match
}

$: boolMatch foo bar
0
$: boolMatch foo foo
1
$: match=$( boolMatch $stringToCheck $patternToUse )