我收到一个字符串,可以是全部数字划分,在这种情况下,我可以接受(例如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);
上面的test
将是true
:我将评估表达式(a < b
)并将其结果存储在一行中的变量test
中。
我想知道是否有可能在Bash中做同样的事情。环顾网络,我没有找到很多例子。感谢this answer,我意识到如果我这样做:
bash$ false_expression=$((2 == 4))
bash$ true_expression=$((2 == 2))
......这两个变量分别假设值为0
和1
。它不完全是true
或false
,但我仍然可以接受它。但是,我似乎无法对我的表达做同样的事情,因为如果我这样做:
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专家,所以我的问题(希望它不是太傻)是:是否可以将评估分配给变量?我可以看到我的if [[ myExpression ]]
被评估为true
,所以我不明白为什么我不能将这个评估分配给变量......有人可以解释一下吗?
如果你真的想用一个任务完成它,那么你可以这样做:
FalseExpression=$( [[ "$InvalidCL" =~ $MyRegex ]] && echo 1 || echo 0)
其中1
代表true
和0
代表false
。但请记住,这不是传统的Bash方式。 Bash中0
的结果表明没有错误,即,如果表达式的计算结果为true
,则退出状态为:
$ echo $?
0
请注意,使用单个(
代表命令替换,而示例中的((
用于评估数学表达式。
传统上,人们可能会这样做:
$ [[ "$InvalidCL" =~ $MyRegex ]]
$ FalseExpression=$?
Bash将最后一个opereation的退出状态存储在'$?'中,其行为方式与$(())
运算符相反。如果表达式是true
而不是$?
将存储0
而$(())将返回1
。如果你来自C背景,后者可能更熟悉。我建议不要混用这些方法。如果一个结果具有不同的含义,则调试脚本可能会非常困难。
你也可以这样做:
[[ ${BUILD_ID} =~ ${REGEX_FOR_ONLY_NUMERICAL_CHANGELISTS} ]]
val=$?
避免调用子shell。同样,val在成功时为0,在失败时为1。
其他人已经指出如何解决正则表达式匹配的布尔返回值。
关于实际问题的措辞,我想指出正则表达式的评估结果实际上自动存储在bash的环境变量中。 $BASH_REMATCH
数组将整个匹配存储在索引0
和捕获组的各自索引处。见:https://www.linuxjournal.com/content/bash-regular-expressions
此阵列中的元素数量也可能比$?
的手动分配更舒适,可用作比赛成功的指标。如果${#BASH_REMATCH[*]}
为零,则最后一个正则表达式不匹配。
您收到了引用的错误消息,因为正则表达式匹配语法仅在[[ ... ]]
构造中定义,而不是在$(( ... ))
arithmetic评估中定义,因此当它看到=
时,它认为您必须尝试某种赋值。
如果要对数字布尔值进行直接单行赋值,则可以在测试中使用“not”运算符。
我强烈建议您在此处添加一些解释性注释。
# assign an integer BOOLEAN value from the test for a match
# the ! means NOT, inverts a 0/1 OS exit code from [[ ]]
match="$( [[ ! "$string" =~ $pattern ]]; echo $?; )"
# now $match is 1 (TRUE) if it *matched* the pattern
为了更清楚,使用其中的注释创建一个函数来封装逻辑,并从一行调用它。
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 )