Regex FreeBSD Bash-无法使用正则表达式对条件进行编码

Regex FreeBSD Bash-无法使用正则表达式对条件进行编码,regex,bash,freebsd,Regex,Bash,Freebsd,我试图为基于FreeBSD的pfSense编写一个脚本。唯一给我带来麻烦的是一个带有正则表达式的条件。简化代码如下: RESPONSE='{"port":98989}' REG='{"port":([0-9]*)}' if [[ $RESPONSE =~ $REG ]]; then PORT=${BASH_REMATCH[1]} fi 启用跟踪模式后,返回的错误如下: + RESPONSE='{"port":98989}' + REG='{"port":([0-9]*)}' + '[[

我试图为基于FreeBSD的pfSense编写一个脚本。唯一给我带来麻烦的是一个带有正则表达式的条件。简化代码如下:

RESPONSE='{"port":98989}'
REG='{"port":([0-9]*)}'
if [[ $RESPONSE =~ $REG ]]; then
    PORT=${BASH_REMATCH[1]}
fi
启用跟踪模式后,返回的错误如下:

+ RESPONSE='{"port":98989}'
+ REG='{"port":([0-9]*)}'
+ '[[' '{"port":98989}' '=~' '{"port":([0-9]*)}' ]]
./pia-port-v2: [[: not found
我不明白为什么
[[
位于跟踪中的单引号之间,这可能就是为什么会出现“未找到”错误

更新

这可能是因为pfSense的FreeBSD不支持bash,而这些说明仅限于bash

有人可以选择bourne shell吗?目标是在表达式匹配时返回端口号

我不熟悉像unix这样的操作系统中的脚本编码


与此同时,我看了一下grep,但它似乎只将regex应用于文件输入。

在使用[[regexps(有时;不总是)时,'和“存在问题,因此我会尝试使用此选项(这对我来说很好):


您应该能够使用来执行此操作,但请注意,它使用,这意味着您需要将括号反斜杠以使其成为捕获:

response='{"port":98989}'
reg='{"port":\([0-9]*\)}'
port=$(expr "$response" : "$reg")
expr
如果正则表达式不匹配,则返回失败,因此可以使用shell条件测试:

port=$(expr "$response" : "$reg") || { echo Failed; }


使用
/bin/sh

#!/bin/sh

response='{"port":98989}'
case $response in
    '{"port":'[0-9]*'}')
        port=${response#*:}     # {"port":98989} --> 98989}
        port=${port%'}'}        # 98989} --> 98989
esac

printf 'response %s yields port %s\n' "$response" "$port"
请注意,
case
语句不使用正则表达式,而是使用shell文件名全局模式。因此,该模式将只匹配一个数字,并触发伪字符串,如
{“port”:0xxx}

如果响应字符串是JSON文档:

$ response='{"port":98989}'
$ printf '%s\n' "$response" | jq .port
98989

在OS X(BSD.BTW的一个变体)上运行良好,请按照惯例使用小写作为用户变量。不相关但值得注意的是:不要在shell脚本中使用所有caps变量名。这些都是为系统和shell实现保留的(这就是为什么您会看到这么多)。您自己的变量应以小写形式正常写入。@rici-已注明。注意:Bash不是FreeBSD上的默认shell。POSIX sh和tcsh在基本系统中可用。除非您安装了Bash包,否则不应使用Bash特定的构造,如
[[
=~
。请参阅以查看语法。是否确实使用
bash
执行此脚本?FreeBSD上的默认shell(即安装为
sh
)不是
bash
。它会发出“未找到”命令“然后我想到了。这一定是因为pfSense的FreeBSD不支持bash。我的问题已经更新。我的代码也在sh中运行,所以只需将#!/bin/bash替换为#!/bin/sh。在pfSense中,它给出了相同的症状。除了第一行之外,脚本与您编写的完全相同。我的代码是”#!/bin/sh-x“。不,我更改了REG=行(已删除“”)@乔纳斯:在你的机器上,/bin/sh是用bash实现的。但并非所有安装都是这样。你永远不应该做出这样的假设。它完成了工作!它正确返回端口号。对于条件部分,我只需要检查端口是否为空。谢谢!@sbeaudoin:你可以检查分配失败。编辑了答案。这是除了jq部分之外,它也可以工作。它给出了一个“jq:not found”。@sbeaudoin是的,您需要安装
jq
端口:
#!/bin/sh

response='{"port":98989}'
case $response in
    '{"port":'[0-9]*'}')
        port=${response#*:}     # {"port":98989} --> 98989}
        port=${port%'}'}        # 98989} --> 98989
esac

printf 'response %s yields port %s\n' "$response" "$port"
$ response='{"port":98989}'
$ printf '%s\n' "$response" | jq .port
98989