Shell 在sh脚本中捕获正则表达式组

Shell 在sh脚本中捕获正则表达式组,shell,sh,Shell,Sh,我正在尝试编写一个shell脚本,默认解释器是/bin/sh 我的脚本如下所示: echo "Starting watchdog" INFO=$(cat /tmp/info) RE="s\=([0-9]+)" if [[$INFO =~ $RE]]; then echo ${BASH_REMATCH[1]}; fi #!/bin/sh RE="s\=([0-9]+)" if egrep "$RE" /tmp/info >/dev/null; then printf 'Found

我正在尝试编写一个shell脚本,默认解释器是
/bin/sh

我的脚本如下所示:

echo "Starting watchdog"
INFO=$(cat /tmp/info)
RE="s\=([0-9]+)"
if [[$INFO =~ $RE]]; then
echo ${BASH_REMATCH[1]};
fi
#!/bin/sh

RE="s\=([0-9]+)"

if egrep "$RE" /tmp/info >/dev/null; then
  printf 'Found it!\n'
fi
我得到的错误如下
test.sh:line 6:[[do:not found


我假设
${BASH\u REMATCH[1]};
不正确,但是如果我使用
sh
而不是
BASH
,我应该使用什么变量来捕获正则表达式呢?

根本没有与此功能等效的
/bin/sh

考虑使用
awk

awk -F= '/s=[[:digit:]]+$/ { print $2; exit(0); }' </tmp/info

awk-F='/s=[[:digit:]+$/{print$2;exit(0);}'您看到的错误是因为您错误地使用了bash条件。
[[
命令前后都需要空格。它不仅仅是一个语言构造,它是一个实际的命令,它将您的部分条件作为选项。也就是说,它是一个仅作为bash内置的命令,而不是您可以在普通POSIX shell脚本中使用的命令

在shell脚本中处理带有变量的正则表达式条件的规范POSIX方法是。也就是说,如果要解析文件,
grep
是一个经典方法

为了避免巴西主义,您可以这样做:

echo "Starting watchdog"
INFO=$(cat /tmp/info)
RE="s\=([0-9]+)"
if [[$INFO =~ $RE]]; then
echo ${BASH_REMATCH[1]};
fi
#!/bin/sh

RE="s\=([0-9]+)"

if egrep "$RE" /tmp/info >/dev/null; then
  printf 'Found it!\n'
fi
或者如果您确实想使用
$INFO
变量执行此操作:

#!/bin/sh

INFO="$(cat /tmp/info)"
RE='.*s=[0-9][0-9]*'

if expr "$INFO" : "$RE" >/dev/null; then
  printf 'Found it!\n'
fi
n=number1 m= ; \
case "$n" in *[0-9]*) ;; *) m="not " ;; esac; printf 'number %sfound\n' "$m"
n=number1 m= p='[0-9]'; \
case "$n" in *$p*) ;; *) m="not " ;; esac ; printf 'number %sfound\n' "$m"
请注意调整后的RE,因为
expr
会自动定位到输入的开头,并且只使用BRE而不是ERE

现在…如果您需要提取括号内看起来要获取的值,那么您需要做更多的解析

#!/bin/sh

RE="s=([0-9]+)"

output="$(egrep -o "$RE" /tmp/info | head 1)"  #  fetch the output, if any
output="${output#s=}"                          #  strip off the "s=" at the beginning

if [ -n "$output" ]; then                      #  if we found anything...
  printf 'Found it: %s!\n' "$output"           #  print it!
fi
请注意使用
egrep
解析ERE,而不是根据您的环境需要调整默认的BRE。(据我所知,一些公司已开始建议不要使用
egrep
,而支持
grep-E

还要注意的是,如果您试图从输入数据中捕获一些看起来更像
abc=foo&jobs=5&s=important+data
,那么您的结果可能不是您所期望的,使用一个类似于上面的re语句。

POSIX shell的内置
case
语句有。模式匹配功能不如regex,但它可以匹配某些内容像
RE=“s\=([0-9]+)”
这样简单的调用

例如,如果
$n
变量中有数字,则匹配:

#!/bin/sh

INFO="$(cat /tmp/info)"
RE='.*s=[0-9][0-9]*'

if expr "$INFO" : "$RE" >/dev/null; then
  printf 'Found it!\n'
fi
n=number1 m= ; \
case "$n" in *[0-9]*) ;; *) m="not " ;; esac; printf 'number %sfound\n' "$m"
n=number1 m= p='[0-9]'; \
case "$n" in *$p*) ;; *) m="not " ;; esac ; printf 'number %sfound\n' "$m"
输出:

number found
number not found
number found
没有号码:

n=number m= ; \
case "$n" in *[0-9]*) ;; *) m="not " ;; esac ; printf 'number %sfound\n' "$m"
输出:

number found
number not found
number found
因此,在一定范围内,模式甚至可以放入变量中:

#!/bin/sh

INFO="$(cat /tmp/info)"
RE='.*s=[0-9][0-9]*'

if expr "$INFO" : "$RE" >/dev/null; then
  printf 'Found it!\n'
fi
n=number1 m= ; \
case "$n" in *[0-9]*) ;; *) m="not " ;; esac; printf 'number %sfound\n' "$m"
n=number1 m= p='[0-9]'; \
case "$n" in *$p*) ;; *) m="not " ;; esac ; printf 'number %sfound\n' "$m"
输出:

number found
number not found
number found

正则表达式支持在
sh
中根本不存在。除非您打算使用不属于shell本身的工具(awk等),否则答案是“您不能”。如果该功能已经存在于
sh
中,为什么bash会为其添加扩展语法?顺便说一句,即使在bash中,您上面的代码也是无效的——您不能省略空格。
[[[$info=~$re]]
,而不是
[[$info=~$re]
。(注意小写变量名的使用——所有大写变量名都可能与shell本身有意义的变量冲突;请参阅POSIX spec@,第四段,保留至少一个小写字符的名称供应用程序使用,并确保它们不会改变POSIX定义工具的行为)…也就是说,您实际上在尝试匹配/提取什么,以及从哪种更大的字符串中提取?工具
sh
确实具有(不是带有匹配组的正则表达式,而是一些简单的fnmatch样式的全局搜索功能)可能足以满足手头的实际用例。