在Linuxbashshell中,可以使用[[命令进行判断。其中,可以使用[[命令的=~运算符来判断一个字符串是否包含特定的模式。有关[[命令的=~运算符的描述,请参见manbash,如下所示:可以使用额外的二元运算符=~,其优先级与==和!=相同。使用时,运算符右侧的字符串被认为是扩展的正则表达式并进行相应匹配。如果字符串与模式匹配,则返回值为0,否则为1。如果正则表达式在语法上不正确,则条件表达式的返回值为2。可以引用模式的任何部分以强制将引用的部分作为字符串进行匹配。也就是说,当使用=~运算符时,右边的字符串被认为是一个扩展的正则表达式。展开后,与左边的字符串比较,看左边的字符串是否包含指定的模式。注意是包含关系,不是完全匹配。即判断右边的模式是否是左边字符串的子串,而不是判断右边的模式是否完全等于左边的字符串。这里提到一个非常关键的点。在给定的扩展正则表达式中,引号括起来的部分将被视为字符串,不再被视为正则表达式。如果=~运算符右边的字符串是用引号括起来的,表示匹配的是字符串本身的内容,不会被解析成正则表达式。如果要将=~运算符右侧的字符串视为正则表达式,则不得将整个字符串括在引号中。不要添加双引号或单引号。这是一个常见的误解,后面会举例说明。注意:只有[[命令支持=~运算符,test命令和[命令都不支持=~运算符。判断一个字符串是否全是数字,使用=~运算符判断一个字符串是否全是数字。假设有一个checkdigits.sh脚本,内容如下:#!/bin/bashfunctioncheck_digits(){localcount=${#1}if[["$1"=~[0-9]{$count}]];然后回显“所有数字”。否则回显“不是所有数字。”fi}check_digits"$1"这个脚本定义了一个check_digits函数。该函数使用${#1}参数扩展表达式获取传入的第一个参数的字符串长度,赋值给count变量。在正则表达式中,[0-9]表示匹配0到9之间的任意数字,但只能匹配一个数字。而[0-9]{n}表示匹配n个连续的数字。[["$1"=~[0-9]{$count}]]表达式中,使用=~运算符判断第一个参数值是否正好匹配count个连续数。如果是,说明第一个参数对应的字符串全是数字,否则不全是数字。checkdigits.sh脚本执行结果如下:$./checkdigits.sh12345Alldigits.$./checkdigits.shabcdNotalldigits.$./checkdigits.sha2cNotalldigits.$./checkdigits.sh1b3Notall数字。请参阅“所有数字”。只有当传入的参数都是数字时才会打印。传入所有字母,或者字母和数字的组合,如果能正确判断不是全是数字,就会打印“Notalldigits.”。由于=~运算符右边的参数是扩展的正则表达式,如果不熟悉正则表达式,在使用时会遇到一些意想不到的异常。下面举例说明判断字符串是否全为数字的一些错误写法,注意避免此类错误。错误方式1假设有一个checkdigits_fake.sh脚本,内容如下:#!/bin/bashfunctioncheck_digits(){if[["$1"=~[0-9]]];然后回显“所有数字”。否则回显“不是所有数字。”fi}check_digits"$1"=~运算符右侧的脚本提供的正则表达式是[0-9],它对应0到9之间的任意数字,但只能是一个数字。那么[["$1"=~[0-9]]]就是判断传入的第一个参数是否包含数字。只要有数字就返回真。它不告诉是否所有字符都是数字。具体执行结果如下:$./checkdigits_fake.sh12345所有数字。$./checkdigits_fake.shabcd不是所有数字。$./checkdigits_fake.sh1b3d所有数字。$./checkdigits_fake.sha2所有数字。“不是所有数字。”只有当参数都是字母时才会打印。传入所有数字,或数字和字母的组合,将打印“所有数字”。此脚本无法准确判断字符是否全部为数字。错误方式2修改checkdigits_fake.sh脚本如下:#!/bin/bashfunctioncheck_digits(){if[["$1"=~[0-9]*]];然后回显“所有数字”。否则回显“不是所有数字。”fi}check_digits"$1"即用[0-9]*匹配零个或多个连续数字。从字面上看,它看起来可以匹配所有数字。但实际上,它仍然会匹配单个数字的大小写。只要有数字就认为是匹配,甚至没有数字的情况下也会匹配。具体执行结果如下:$./checkdigits_fake.sh12345所有数字.$./checkdigits_fake.shabcd所有数字.$./checkdigits_fake.sh1b3d所有数字.$./checkdigits_fake.sha2所有数字。无论参数是全数字,全字母,还是数字和字母的组合,都会打印“Alldigits.”,并且都符合给定的[0-9]*模式。即此脚本无法达到判断字符串是否全为数字的效果。同样,[0-9]+匹配一个或多个连续数字。使用这种方式也不能判断字符串是否全是数字。错误3前面说到,如果=~运算符右边的字符串用双引号括起来,则表示会匹配字符串本身的内容,不再解析成正则表达式。例如[0-9]对应于正则表达式中的一个数字。但是“[0-9]”对应的是字符串“[0-9]”,不再对应一个数字。虽然上面的[["$1"=~[0-9]{$count}]]表达式可以正确判断字符串是否都是数字。一旦[0-9]{$count}用双引号括起来写成[["$1"=~"[0-9]{$count}"]],就会出错。可以修改checkdigits.sh脚本代码进行校验。下面用例子来说明:$[["123"=~[0-9]{3}]];echo$?0$[["123"=~"[0-9]{3}"]];echo$?1$[["[0-9]{3}"=~[0-9]{3}]];echo$?1$[["[0-9]{3}"=~"[0-9]{3}"]];echo$?0可以看到[["123"=~[0-9]{3}]]正确判断了“123”字符串包含三个连续的数字。带有echo$?的打印命令的返回值?为0,这是正确的。而[["123"=~"[0-9]{3}"]]命令的返回值为1,对应false,表示要比较的两个字符串不匹配。“[0-9]{3}”此时不再是匹配三个连续的数字,而是匹配字符串“[0-9]{3}”本身。[["[0-9]{3}"=~[0-9]{3}]]命令中,右边的[0-9]{3}没有双引号,会按照到正则表达式,这意味着匹配三个连续的数字。而左边的字符串没有三个连续的数字,所以返回1,不匹配。在[["[0-9]{3}"=~"[0-9]{3}"]]命令中,右边的"[0-9]{3}"是双引号,不是不再视为正则表达式处理。这只比较字符串本身,所以返回0,这是一个匹配项。在bash中,为了避免分词引起的意外行为,字符串或变量值通常用双引号括起来。但是在使用=~操作符的时候,要注意检查右边的字符串是不是要当作正则表达式来处理。如果是,请不要加双引号。判断一个字符串是否是另一个字符串的子串我们可以使用=~操作来判断一个字符串是否是另一个字符串的子串。要判断的字符串要写在操作符的右边,要判断的字符串要写在操作符的左边。假设有一个check_substr.sh脚本,内容如下:#!/bin/bashfunctioncheck_substr(){if[["$1"=~"$2"]];thenecho\"$1\"contains\"$2\"elseecho\"$1\"doesnotcontain\"$2\"fi}check_substr"$1""$2"这个脚本检查传入的第二个参数是否是第一个参数。具体执行结果如下:$./check_substr.sh"Thisisateststring""teststring""Thisisateststring"contains"teststring"$./check_substr.sh"Thisisateststring""isatest""Thisisateststring"包含"isatest"$./check_substr.sh"Thisisateststring""isatest""Thisisateststring"不包含"isatest"$./check_substr.sh"Thisisateststring""newstring""Thisisateststring"doesnotcontain"newstring"测试时,如果传入的字符串参数包含空格,必须用双引号括起来。注意:=~右边的“$2”是双引号,不再作为正则表达式处理,只会比较字符串本身的内容。
