我想检查一个字符串是否以“节点”开始,例如。“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

其他回答

我更喜欢已经发布的其他方法,但有些人喜欢使用:

case "$HOST" in 
    user1|node*) 
            echo "yes";;
        *)
            echo "no";;
esac

编辑:

我已经在上面的案例陈述中添加了你的替补

在你编辑过的版本中,括号太多了。它应该是这样的:

if [[ $HOST == user1 || $HOST == node* ]];

你可以选择你想要检查的字符串部分:

if [ "${HOST:0:4}" = user ]

对于你接下来的问题,你可以使用OR:

if [[ "$HOST" == user1 || "$HOST" == node* ]]
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

@OP,对于你的两个问题,你可以使用case/esac:

string="node001"
case "$string" in
  node*) echo "found";;
  * ) echo "no node";;
esac

第二个问题

case "$HOST" in
 node*) echo "ok";;
 user) echo "ok";;
esac

case "$HOST" in
 node*|user) echo "ok";;
esac

或者Bash 4.0

case "$HOST" in
 user) ;&
 node*) echo "ok";;
esac

在Mark Rushakoff的最高级别答案中添加了更多的语法细节。

表达式

$HOST == node*

也可以写成

$HOST == "node"*

效果是一样的。只要确保通配符在引用的文本之外。如果通配符在引号内,它将按字面解释(即不是通配符)。