views:

861

answers:

6

Hi,

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?

Thanks!


UPDATE:

Thank you so much! 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? Thanks!

+4  A: 

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* ]]
martin clayton
Thanks, Martin! I added to the original post a new question about how to combine expressions in if cluase.
Tim
+3  A: 

If you're using a recent bash (v3+) suggest bash regex comparison operator =~, i.e.

if [[ "$HOST" =~ user.* ]]; then
    echo "yes"
fi

To match this or that in a regex use |, i.e.

if [[ "$HOST" =~ user.*|host1 ]]; then
    echo "yes"
fi

Note - these is 'proper' regular expression syntax.

  • user* means use and zero-or-more occurrences of r, so use and userrrr will match.
  • user.* means user and zero-or-more occurrences of any character, so user1, userX will match. If you're not familiar with regular expression syntax, try referring to this resource.

Note - it's better if you ask each new question as a new question, makes stackoverflow tidier and more useful. You can always include a link back to a previous question for reference.

Brabster
Thanks, Brabster! I added to the original post a new question about how to combine expressions in if cluase.
Tim
+6  A: 

This snippet on the Advanced Bash Scripting Guide says:

The == comparison operator behaves differently within a double-brackets  test than within single brackets.

[[ $a == z* ]]   # True if $a starts with an "z" (regex pattern matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).

So you had it nearly correct; you needed double brackets, not single brackets.


With regards to your second question, you can write it this way:

HOST=user1
if  [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
    echo yes1
fi

HOST=node001
if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
    echo yes2
fi

Which will echo

yes1
yes2

Bash's if syntax is hard to get used to (IMO).

Mark Rushakoff
Thanks, Mark! I added to the original post a new question about how to combine expressions in if cluase.
Tim
+6  A: 

I prefer the other methods already posted, but some people like to use:

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

Edit:

I've added your alternates to the case statement above

In your edited version you have too many brackets. It should look like this:

if [[ $HOST == user1 || $HOST == node* ]];
Dennis Williamson
Thanks, Dennis! I added to the original post a new question about how to combine expressions in if cluase.
Tim
+1  A: 
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
just somebody
`[` and `test` are Bash builtins as well as external programs. Try `type -a [`.
Dennis Williamson
thx, edited, hopefully for the better.
just somebody
+2  A: 

@OP, for both your questions you can use case/esac

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

second question

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

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

OR Bash 4.0

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