In bash, how can I check if a string begins with s

2019-01-02 16:44发布

I would like to check if a string begins with "node" e.g. "node001". Something like

if [ $HOST == user* ]  
  then  
  echo yes  
fi

How can I do it correctly?


I further need to combine expressions to check if HOST is either "user1" or begins with "node"

if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];  
then  
echo yes 
fi

> > > -bash: [: too many arguments

How to do it correctly?

11条回答
余生无你
2楼-- · 2019-01-02 17:06

You can select just the part of the string you want to check:

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

For your follow-up question, you could use an OR:

if [[ $HOST == user1 || $HOST == node* ]]
查看更多
人气声优
3楼-- · 2019-01-02 17:06

Adding a tiny bit more syntax detail to Mark Rushakoff's highest rank answer.

The expression

$HOST == node*

Can also be written as

$HOST == "node"*

The effect is the same. Just make sure the wildcard is outside the quoted text. If the wildcard is inside the quotes it will be interpreted literally (i.e. not as a wildcard).

查看更多
素衣白纱
4楼-- · 2019-01-02 17:09

While I find most answers here quite correct, many of them contain unnecessary bashisms. POSIX parameter expansion gives you all you need:

[ "${host#user}" != "${host}" ]

and

[ "${host#node}" != "${host}" ]

${var#expr} strips the smallest prefix matching expr from ${var} and returns that. Hence if ${host} does not start with user (node), ${host#user} (${host#node}) is the same as ${host}.

expr allows fnmatch() wildcards, thus ${host#node??} and friends also work.

查看更多
余生请多指教
5楼-- · 2019-01-02 17:12

Another thing you can do is cat out what you are echoing and pipe with inline cut -c 1-1

查看更多
低头抚发
6楼-- · 2019-01-02 17:15
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];  
then  
echo yes 
fi

doesn't work, because all of [, [[ and test recognize the same nonrecursive grammar. see section CONDITIONAL EXPRESSIONS in your bash man page.

As an aside, the SUSv3 says

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.

you'd need to write it this way, but test doesn't support it:

if [ $HOST == user1 -o $HOST == node* ];  
then  
echo yes 
fi

test uses = for string equality, more importantly it doesn't support pattern matching.

case / esac has good support for pattern matching:

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

it has the added benefit that it doesn't depend on bash, the syntax is portable. from the Single Unix Specification, The Shell Command Language:

case word in
    [(]pattern1) compound-list;;
    [[(]pattern[ | pattern] ... ) compound-list;;] ...
    [[(]pattern[ | pattern] ... ) compound-list]
esac
查看更多
登录 后发表回答