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

问题描述 投票:2回答:4

我收到一个字符串,可以是全部数字划分,在这种情况下,我可以接受(例如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))

......这两个变量分别假设值为01。它不完全是truefalse,但我仍然可以接受它。但是,我似乎无法对我的表达做同样的事情,因为如果我这样做:

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,所以我不明白为什么我不能将这个评估分配给变量......有人可以解释一下吗?

regex bash
4个回答
3
投票

如果你真的想用一个任务完成它,那么你可以这样做:

FalseExpression=$( [[ "$InvalidCL" =~ $MyRegex ]] && echo 1 || echo 0)

其中1代表true0代表false。但请记住,这不是传统的Bash方式。 Bash中0的结果表明没有错误,即,如果表达式的计算结果为true,则退出状态为:

$ echo $?
0

请注意,使用单个(代表命令替换,而示例中的((用于评估数学表达式。

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

$ [[ "$InvalidCL" =~ $MyRegex ]]
$ FalseExpression=$?

Bash将最后一个opereation的退出状态存储在'$?'中,其行为方式与$(())运算符相反。如果表达式是true而不是$?将存储0而$(())将返回1。如果你来自C背景,后者可能更熟悉。我建议不要混用这些方法。如果一个结果具有不同的含义,则调试脚本可能会非常困难。


1
投票

你也可以这样做:

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

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


1
投票

其他人已经指出如何解决正则表达式匹配的布尔返回值。

关于实际问题的措辞,我想指出正则表达式的评估结果实际上自动存储在bash的环境变量中。 $BASH_REMATCH数组将整个匹配存储在索引0和捕获组的各自索引处。见:https://www.linuxjournal.com/content/bash-regular-expressions

此阵列中的元素数量也可能比$?的手动分配更舒适,可用作比赛成功的指标。如果${#BASH_REMATCH[*]}为零,则最后一个正则表达式不匹配。

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


1
投票

如果要对数字布尔值进行直接单行赋值,则可以在测试中使用“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 )
© www.soinside.com 2019 - 2024. All rights reserved.