#!/bin/sh
re="\/$"
if [ $1 =~ $re ]; then
echo "${ATTENTION_PREFIX}$1 DIRECTORY MAY NOT CONTAIN A \"/\" OR LITERAL SLASH!${ATTENTION_POSTFIX}"
exit 1
fi
执行./file.sh hello/
结果为[: 29: hello: unexpected operator
看来这个正则表达式方法对于 shell 脚本来说是不正确的。
答案1
标准test
命令也称为[
没有=~
运算符。现在大多数 shell 都内置了该命令。
Korn shell 引入了具有替代语法和不同解析规则的[[...]]
构造(不是命令)。[[
zsh
并bash
在一定程度上复制了它,但有限制和许多差异,但从未标准化,因此不应在可移植sh
脚本中使用。
ksh93
总是有办法将扩展的正则表达式转换为它的通配符:
pattern=${ printf %P "regexp"; }
然后你可以这样做:
[[ $var = $pattern ]]
之后 (2001 年 ksh93l)它还在其 glob 中合并了正则表达式,就像~(E)regex
扩展正则表达式的语法一样,因此您可以执行以下操作:
[[ $var = ~(E)regex ]]
这种模式匹配仅适用于[[...]]
构造 or case
,不适用于[
命令。
zsh
为其[
命令添加了正则表达式匹配运算符,并[[...]]
在 2001 年首次使用pcre
模块添加了正则表达式匹配运算符。语法最初是[ string -pcre-match regex ]
or [[ string -pcre-match regex ]]
。
bash
=~
bash 3.0添加了一个运算符(2004 年)。使用扩展正则表达式。不久之后 ksh93 和 zsh 也添加了这一点(同样存在差异)。
ksh93
和bash-3.2
以上(当该compat31
选项未启用时)使用引号逃脱regexp 运算符会导致各种混乱(并且在 ksh93 中存在很多错误),这意味着它不能与[
那里的命令以相同的方式使用。zsh
没有这个问题(引号用于 shell 引用,反斜杠像往常一样转义正则表达式运算符),因此该运算符在的命令=~
中工作(尽管它本身需要引号,因为它是 中的文件名扩展运算符)。zsh
[
=foo
zsh
yash
没有,[[...]]
但它的[
命令有一个=~
运算符(使用 ERE)并且按您的预期工作(如zsh
's)。
(2023年编辑)[[...]]
在 2.49 (2018) 中添加了对 yash 的支持,并且=~
在引用方面与 bash 类似。
无论如何, 和 都不[[...]]
是POSIX 运算符,也不应该在脚本=~
中使用。sh
对字符串进行正则表达式匹配的标准命令是expr
:
if expr "x$var" : "x$regex" > /dev/null; then...
请注意,expr
正则表达式是在开始时锚定的,您需要这个x
技巧来避免运算$var
符值出现问题expr
。expr
使用基本正则表达式,而不是扩展正则表达式。
然而,大多数时候,您不需要正则表达式,因为简单的 shell 模式匹配对于大多数情况来说就足够了:
case $var in
(pattern) echo matches
esac
答案2
更改#!/bin/sh
为#!/bin/bash
, 并使用双括号代替:
if [[ $1 =~ $re ]]; then
这是扩展测试命令,与(常规)测试命令相反。=~
只能与[[ ... ]]
版本一起使用,并且需要 Bash 3.0 或更高版本。
答案3
在bash
旧测试中[
不支持正则表达式。您必须使用新的测试[[
来代替:
re="\/$"
if [[ $1 =~ $re ]]; then
echo "${ATTENTION_PREFIX}$1 DIRECTORY MAY NOT CONTAIN A \"/\" OR LITERAL SLASH!${ATTENTION_POSTFIX}"
exit 1
fi
你可以看到更多这里。
您还需要将#!/bin/sh
shebang 行更改为#!/bin/bash
。