我收到的字符串可以全为破折号,在这种情况下,对我来说是可接受的(例如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专家,所以我的问题(希望它不是很傻)是:是否可以将评估分配给变量?我可以看到我的{{1 }}被评估为if [[ myExpression ]]
,所以我不明白为什么我无法将此评估分配给变量。有人可以解释吗?
答案 0 :(得分:3)
如果您真的想一次完成任务,那么可以这样做:
FalseExpression=$( [[ "$InvalidCL" =~ $MyRegex ]] && echo 1 || echo 0)
其中1
代表true
,0
代表false
。但是请记住,这不是传统的Bash方法。 Bash中0
的结果表示没有错误,即,如果表达式的计算结果为true
,则退出状态为:
$ echo $?
0
请注意,使用单个(
代表命令替换,而示例中的((
则评估数学表达式。
传统上,人们可能会这样做:
$ [[ "$InvalidCL" =~ $MyRegex ]]
$ FalseExpression=$?
Bash将最后一次操作的退出状态存储在“ $?”中,其行为与$(())
运算符相反。如果表达式为true
,则$?
将存储0
,而$ {{}}将返回1
。如果您来自C背景,可能对后者更熟悉。我建议不要混合使用这些方法。如果一个结果可能具有不同的含义,则调试脚本可能会非常困难。
答案 1 :(得分:1)
您也可以这样做:
[[ ${BUILD_ID} =~ ${REGEX_FOR_ONLY_NUMERICAL_CHANGELISTS} ]]
val=$?
避免调用子shell。同样,成功时val为0,失败时为1。
答案 2 :(得分:1)
如果您希望将单行直接分配给数字布尔值,则可以在测试中使用“非”运算符。
我 强烈 建议您为此添加一些解释性评论。
# 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 )
答案 3 :(得分:1)
其他人已经指出了如何解决获取正则表达式匹配的 boolean返回值的问题。
关于实际问题的措词,我想指出的是,一个regex表达式的求值结果实际上自动存储在bash的环境变量中。 $BASH_REMATCH
数组将整个匹配项存储在索引0
处,并将捕获组存储在它们各自的索引处。参见:https://www.linuxjournal.com/content/bash-regular-expressions
与$?
中的手动分配相比,该数组中的元素数量也可能更舒适,可以用作匹配成功的指标。如果${#BASH_REMATCH[*]}
为零,则最后一个正则表达式不匹配。
您得到的错误消息是因为正则表达式匹配语法仅在[[ ... ]]
构造中定义,而不是在$(( ... ))
算术评估中定义,因此当它看到=
时会认为您认为必须尝试某种分配。