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 16:48

since # has a meaning in bash I got to the following solution.
In addition I like better to pack strings with "" to overcome spaces etc.

A="#sdfs"
if [[ "$A" == "#"* ]];then
    echo "skip comment line"
fi
查看更多
明月照影归
3楼-- · 2019-01-02 16:48

@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
查看更多
君临天下
4楼-- · 2019-01-02 16:49

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* ]];
查看更多
一个人的天荒地老
5楼-- · 2019-01-02 17:00

If you're using a recent bash (v3+), I 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 - this 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.
  • ^user.* means match the pattern user.* at the begin of $HOST.

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, it makes stackoverflow tidier and more useful. You can always include a link back to a previous question for reference.

查看更多
几人难应
6楼-- · 2019-01-02 17:04

I always try to stick with POSIX sh instead of using bash extensions, since one of the major points of scripting is portability. (Besides connecting programs, not replacing them)

In sh, there is an easy way to check for an "is-prefix" condition.

case $HOST in node*)
    your code here
esac

Given how old, arcane and crufty sh is (and bash is not the cure: It's more complicated, less consistent and less portable), I'd like to point out a very nice functional aspect: While some syntax elements like case are built-in, the resulting constructs are no different than any other job. They can be composed in the same way:

if case $HOST in node*) true;; *) false;; esac; then
    your code here
fi

Or even shorter

if case $HOST in node*) ;; *) false;; esac; then
    your code here
fi

Or even shorter (just to present ! as a language element -- but this is bad style now)

if ! case $HOST in node*) false;; esac; then
    your code here
fi

If you like being explicit, build your own language element:

beginswith() { case $2 in "$1"*) true;; *) false;; esac; }

Isn't this actually quite nice?

if beginswith node "$HOST"; then
    your code here
fi

And since sh is basically only jobs and string-lists (and internally processes, out of which jobs are composed), we can now even do some light functional programming:

beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
checkresult() { if [ $? = 0 ]; then echo TRUE; else echo FALSE; fi; }

all() {
    test=$1; shift
    for i in "$@"; do
        $test "$i" || return
    done
}

all "beginswith x" x xy xyz ; checkresult  # prints TRUE
all "beginswith x" x xy abc ; checkresult  # prints FALSE

This is elegant. Not that I'd advocate using sh for anything serious -- it breaks all too quickly on real world requirements (no lambdas, so must use strings. But nesting function calls with strings is not possible, pipes are not possible...)

查看更多
低头抚发
7楼-- · 2019-01-02 17:06

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 a "z" (wildcard 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).

查看更多
登录 后发表回答