我想检查一个字符串是否以“节点”开始,例如。“node001”。类似的
if [ $HOST == user* ]
then
echo yes
fi
我怎样才能正确地做呢?
我进一步需要组合表达式来检查HOST是否为“user1”或以“node”开头
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
> > > -bash: [: too many arguments
我怎样才能正确地做呢?
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
不起作用,因为所有的[、[[和test都识别相同的非递归语法。请参阅Bash手册页上的条件表达式部分。
说句题外话,SUSv3说
The KornShell-derived conditional command (double bracket [[]]) was removed from the shell command language description in an early proposal. Objections were raised that the real problem is misuse of the test command ([), and putting it into the shell is the wrong way to fix the problem. Instead, proper documentation and a new shell reserved word (!) are sufficient.
Tests that require multiple test operations can be done at the shell level using individual invocations of the test command and shell logicals, rather than using the error-prone -o flag of test.
你需要这样写,但是test不支持:
if [ $HOST == user1 -o $HOST == node* ];
then
echo yes
fi
Test使用=表示字符串相等,更重要的是它不支持模式匹配。
Case / esac对模式匹配有很好的支持:
case $HOST in
user1|node*) echo yes ;;
esac
它还有一个额外的好处,那就是它不依赖于Bash,而且语法是可移植的。从单一Unix规范,Shell命令语言:
case word in
[(]pattern1) compound-list;;
[[(]pattern[ | pattern] ... ) compound-list;;] ...
[[(]pattern[ | pattern] ... ) compound-list]
esac
如果您正在使用最新版本的Bash (v3+),我建议使用Bash正则表达式比较运算符=~,例如,
if [[ "$HOST" =~ ^user.* ]]; then
echo "yes"
fi
要在正则表达式中匹配这个或那个,使用|,例如,
if [[ "$HOST" =~ ^user.*|^host1 ]]; then
echo "yes"
fi
注意——这是“正确的”正则表达式语法。
User *表示使用和零次或多次出现r,因此使用和userrrr将匹配。
用户。*表示用户和零或多次出现任何字符,因此user1, userX将匹配。
^用户。*表示匹配模式用户。*在$HOST的开头。
如果您不熟悉正则表达式语法,请尝试参考此资源。
请注意,Bash =~操作符仅在右侧为unquote时进行正则表达式匹配。如果你在右边引用,“模式的任何部分都可以被引用,以迫使它作为字符串进行匹配。”即使在进行参数展开时,也不应该在右边引用。
我调整了@markrushakoff的答案,使其成为一个可调用的函数:
function yesNo {
# Prompts user with $1, returns true if response starts with y or Y or is empty string
read -e -p "
$1 [Y/n] " YN
[[ "$YN" == y* || "$YN" == Y* || "$YN" == "" ]]
}
像这样使用它:
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] y
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] Y
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] yes
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n]
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] n
false
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] ddddd
false
下面是一个更复杂的版本,提供了一个指定的默认值:
function toLowerCase {
echo "$1" | tr '[:upper:]' '[:lower:]'
}
function yesNo {
# $1: user prompt
# $2: default value (assumed to be Y if not specified)
# Prompts user with $1, using default value of $2, returns true if response starts with y or Y or is empty string
local DEFAULT=yes
if [ "$2" ]; then local DEFAULT="$( toLowerCase "$2" )"; fi
if [[ "$DEFAULT" == y* ]]; then
local PROMPT="[Y/n]"
else
local PROMPT="[y/N]"
fi
read -e -p "
$1 $PROMPT " YN
YN="$( toLowerCase "$YN" )"
{ [ "$YN" == "" ] && [[ "$PROMPT" = *Y* ]]; } || [[ "$YN" = y* ]]
}
像这样使用它:
$ if yesNo "asfd" n; then echo "true"; else echo "false"; fi
asfd [y/N]
false
$ if yesNo "asfd" n; then echo "true"; else echo "false"; fi
asfd [y/N] y
true
$ if yesNo "asfd" y; then echo "true"; else echo "false"; fi
asfd [Y/n] n
false