FreeBSD Bash - 无法使用正则表达式对条件进行编码
FreeBSD Bash - Unable to code a condition with regex
我正在尝试为基于 FreeBSD 的 pfSense 编写脚本。唯一给我带来麻烦的部分是正则表达式的条件。简化代码是这样的:
RESPONSE='{"port":98989}'
REG='{"port":([0-9]*)}'
if [[ $RESPONSE =~ $REG ]]; then
PORT=${BASH_REMATCH[1]}
fi
启用跟踪模式后,错误 returned 如下:
+ RESPONSE='{"port":98989}'
+ REG='{"port":([0-9]*)}'
+ '[[' '{"port":98989}' '=~' '{"port":([0-9]*)}' ]]
./pia-port-v2: [[: not found
我不明白为什么 [[
在跟踪中的单引号之间,这可能是 "not found" 错误发生的原因。
更新
可能是因为pfSense的FreeBSD不支持bash,这些说明只是bash。我发现在写完这个问题并试图找到答案之后。
有人可以替代伯恩 shell 吗?如果表达式匹配,目标是 return 端口号。
我对 unix 中的脚本编码很陌生,比如 OS。
同时,我查看了 grep,但它似乎只将正则表达式应用于文件输入。
使用 [[ 正则表达式(有时;不总是)时 ' 和 " 有问题,所以我会试试这个(这对我来说很好):
#!/bin/bash
REG=\{\"port\"\:\([0-9]\*\)\} # This line is altered
RESPONSE='{"port":98989}'
if [[ $RESPONSE =~ $REG ]]; then
echo funkar
fi
您应该可以使用 expr
utility to do this, but note that it use Posix basic regexps,这意味着您需要用反斜杠将括号变成捕获:
response='{"port":98989}'
reg='{"port":\([0-9]*\)}'
port=$(expr "$response" : "$reg")
expr
returns 如果正则表达式不匹配则失败,因此您可以使用 shell 条件来测试:
port=$(expr "$response" : "$reg") || { echo Failed; }
或
if ! port=$(expr "$response" : "$reg"); then
# Do something on failure
fi
与/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
我正在尝试为基于 FreeBSD 的 pfSense 编写脚本。唯一给我带来麻烦的部分是正则表达式的条件。简化代码是这样的:
RESPONSE='{"port":98989}'
REG='{"port":([0-9]*)}'
if [[ $RESPONSE =~ $REG ]]; then
PORT=${BASH_REMATCH[1]}
fi
启用跟踪模式后,错误 returned 如下:
+ RESPONSE='{"port":98989}'
+ REG='{"port":([0-9]*)}'
+ '[[' '{"port":98989}' '=~' '{"port":([0-9]*)}' ]]
./pia-port-v2: [[: not found
我不明白为什么 [[
在跟踪中的单引号之间,这可能是 "not found" 错误发生的原因。
更新
可能是因为pfSense的FreeBSD不支持bash,这些说明只是bash。我发现在写完这个问题并试图找到答案之后。
有人可以替代伯恩 shell 吗?如果表达式匹配,目标是 return 端口号。
我对 unix 中的脚本编码很陌生,比如 OS。
同时,我查看了 grep,但它似乎只将正则表达式应用于文件输入。
使用 [[ 正则表达式(有时;不总是)时 ' 和 " 有问题,所以我会试试这个(这对我来说很好):
#!/bin/bash
REG=\{\"port\"\:\([0-9]\*\)\} # This line is altered
RESPONSE='{"port":98989}'
if [[ $RESPONSE =~ $REG ]]; then
echo funkar
fi
您应该可以使用 expr
utility to do this, but note that it use Posix basic regexps,这意味着您需要用反斜杠将括号变成捕获:
response='{"port":98989}'
reg='{"port":\([0-9]*\)}'
port=$(expr "$response" : "$reg")
expr
returns 如果正则表达式不匹配则失败,因此您可以使用 shell 条件来测试:
port=$(expr "$response" : "$reg") || { echo Failed; }
或
if ! port=$(expr "$response" : "$reg"); then
# Do something on failure
fi
与/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