在bash中,如何检查一个string是否以某个值开始?

我想检查一个string是否以“node”开头,例如“node001”。 就像是

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

我怎样才能正确地做到这一点?


我还需要结合expression式来检查HOST是“user1”还是以“node”开始

 if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ]; then echo yes fi > > > -bash: [: too many arguments 

如何正确地做到这一点?

高级Bash脚本指南上的这段代码说:

 # 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). 

所以你几乎是正确的; 你需要括号,而不是单个括号。


关于你的第二个问题,你可以这样写:

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

这将回声

 yes1 yes2 

Bash的语法很难习惯(IMO)。

如果你使用最近的bash(v3 +),build议bash正则expression式比较运算符=~ ,即

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

要匹配this or that在正则expression式中使用| 即,

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

注意 – 这是“正确的”正则expression式语法。

  • user*表示use r和零次或多次出现,所以useuserrrr会匹配。
  • user.*表示任何字符的user和零次或多次出现,所以user1userX将匹配。
  • ^user.*表示匹配$ HOST开头的模式user.*

如果您不熟悉正则expression式语法,请尝试引用此资源 。

注意 – 如果你将每个新问题作为一个新问题提出来,那么更好的做法是使计算器更加整洁和更有用。 您可以随时将链接添加回上一个问题以供参考。

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

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

编辑:

我已经在上面的case语句中添加了你的替代者

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

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

您只能select要检查的string的一部分:

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

对于你的后续问题,你可以使用OR :

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

我总是试图坚持使用POSIX sh,而不是使用bash扩展,因为脚本的一个主要点是可移植性。 (除了连接程序,不能replace它们)

在sh中,有一个简单的方法来检查“is-prefix”条件。

 case $HOST in node*) your code here esac 

鉴于年龄,神秘和笨重sh(而且bash不是治愈方法:它更复杂,更不一致,更不便携),我想指出一个非常好的function方面:虽然内置了一些语法元素,所得到的结构与其他任何工作没有区别。 他们可以用相同的方式组成:

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

甚至更短

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

或者甚至更短(只是将其作为一种语言元素来呈现 – 但现在这是糟糕的风格)

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

如果你喜欢明确,build立你自己的语言元素:

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

这不是很好吗?

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

而且由于sh基本上只是作业和string列表(以及内部处理,哪些作业是由其组成的),我们现在甚至可以做一些轻量级的函数式编程:

 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 

这是优雅的。 不是我主张使用sh来处理任何严重的事情 – 它在现实世界的要求中不能太快(没有lambdaexpression式,所以必须使用string,但是用string嵌套函数是不可能的,pipe道是不可能的)

因为#在bash中有一个含义我得到了以下解决scheme。
此外,我更喜欢用“”来包装string来克服空间等。

 A="#sdfs" if [[ "$A" == "#"* ]];then echo "skip comment line" fi 

虽然我在这里find大多数答案都是非常正确的,但是其中很多答案都是不必要的。 POSIX参数扩展为您提供所有您所需要的:

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

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

${var#expr}${var}剥离最小的前缀匹配expr并返回。 因此,如果${host}不以usernode )开始,则${host#user}${host#node} )与${host}相同。

expr允许fnmatch()通配符,因此${host#node??}和朋友也可以工作。

@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 
 if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ]; then echo yes fi 

不起作用,因为所有的[[[testing都认出了同样的非recursion语法。 请参阅bash手册页中的CONDITIONAL EXPRESSIONS部分。

另外,SUSv3说

在早期的提议中,从shell命令语言描述中删除了KornShell派生的条件命令(双括号[[]] )。 反对意见认为,真正的问题是滥用testing命令( [ ),并将其放入shell是解决问题的错误方法。 相反,正确的文档和一个新的shell保留字( )就足够了。

需要多个testing操作的testing可以在shell级别使用testing命令和shell逻辑的单独调用来完成,而不是使用testing的错误倾向-o标志。

你需要这样写,但是testing不支持:

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

testing使用= forstring相等,更重要的是它不支持模式匹配。

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 

你可以做的另一件事是找出你正在呼应的内容和pipe道inline cut -c 1-1