如何在bash中进行文本匹配

我试图find一个很好的方式来检查一些文本,以设置一个variables。 例如执行逻辑:'如果版本string是1.x然后设置一个标志'。 这样做的一个方法是:

versionFlag="0" if grep -q "^1.*" versionfile; then versionFlag="1" fi 

这是一个有点冗长。 如果我想切换多种可能性,那么这很容易:

 case `grep "^1.*" versionfile` in 1.*) echo "version 1" ;; ... esac 

但是,如果某些文本匹配正则expression式或通配符,那么只需将标志设置为true或false,就可以实现一条很好的线路?

 versionFlag=`grep "^1.*" /tmp/test | wc -l` 

versionFlag然后设置为0.testing匹配中的任何数据, versionFlag被设置为匹配的行数,所以

 if [ $versionFlag == 0 ] ; then echo false else echo true fi 

编辑:这可以更简单地完成

 versionFlag=$(grep "^1.*" /tmp/test -c) 

这将返回文件中的实例计数

你可以在bash 3.x中做这样的事情(旧版本不支持正则expression式匹配)

 version=`cat versionfile` [[ $version =~ "^1.*" ]] && versionFlag=1 

在bash中没有三元运算符(例如?:),所以你用if来坚持,然后构造多行。 你可以使用另一种具有三元运算符的语言(例如PERL)。

请注意,许多民间人士不鼓励使用三元运算符,因为它们不易于在代码中读取 – 换句话说,您的注释最终会比多行代码更长。

我怀疑这两种方法都有性能优势。

实际上,这个构造:

[[ $version =~ ^1\.+ ]] && versionFlag=1

很容易扩展到支持“不符合”的情况; 只是这样做:

[[ $version =~ ^1\.+ ]] && versionFlag=1 || versionFlag=0

顺便提一下,请注意正则expression式中从“*”到“+”的变化。 使用星号,正则expression式在版本值“10”上仍然会错误匹配。 ('*'修饰符的意思是“匹配零次或多次出现”,即,你仍然不需要有一个小数点;'+'修饰符的意思是“匹配一个或多个事件”)。 ,意思是“1”(即没有小数的值) 匹配; 这可能会或可能不会成为您的应用程序的问题。

如果没有使用正则expression式匹配运算符,还有一种方法可以做到这一点; 尝试这个:

[[ ${version#1.} != ${version} ]] && versionFlag=1 || versionFlag=0

这只是一个模式匹配,而不是正则expression式,所以如果你真的需要正则expression式的function,它不会工作,但对于简单的东西,这是伟大的。 (如果您不熟悉这种forms的参数扩展,则“$ {version#1。}”构造扩展为“version”的值,但是从值的开始处删除后面的“#”例如:如果“version”的值为“1.03”,则“$ {version#1。}”的结果为“03”,因为这与原始值不同,所以“!=”testing成功。)