如何根据 Bash 版本/功能编写条件代码?
How to write conditional code depending on Bash version / features?
我在我的 Bash 脚本之一中使用了 =~
。但是,我需要使脚本与不支持该运算符的 Bash 版本兼容,特别是 msysgit which is not build against libregex 附带的 Bash 版本。我有一个使用 expr match
的解决方法,但由于某种原因,它在 Mac OS X 上再次不起作用。
因此,我只想使用 expr match
if [ -n "$MSYSTEM" -a ${BASH_VERSINFO[0]} -lt 4 ]
,否则使用 =~
。问题是 Bash 似乎总是解析整个脚本,即使 msysgit Bash 会在运行时执行解决方法,它在解析脚本时仍然会偶然发现 =~
。
是否可以根据 Bash 版本在同一脚本中有条件地执行代码,或者我应该寻找另一种方法来解决这个问题?
我目前的解决方案是在所有平台上使用 grep -q
。这避免了任何条件或复杂的代码结构。
可能仅在运行时使用 eval
来解析包含 =~
的代码也可行,但话又说回来,这会使代码更难阅读。
对于您的情况,您可以用等效的模式匹配替换正则表达式。
[[ $foo = \[+([0-9])\][[:space:]]* ]]
一些解释:
模式与整个字符串匹配。以下正则表达式和模式是等效的:
^foo$
和 foo
^foo
和 foo*
foo$
和 *foo
foo
和 *foo*
+(...)
匹配封闭模式的一次或多次出现,在本例中为 [0-9]
。也就是说,如果 $pattern
和 $regex
匹配相同的字符串,那么 +($pattern)
和 ($regex)+
.
对于这个特定的模式,可以阐明等效但可移植的 case
语句。不过,它需要有相当多的不同 glob 模式来枚举所有极端情况。
case $foo in
[![]* | \[[!0-9]* | *[!][0-9[:space:]]* | *[!0-9[:space:]] | \
*\]*[![:space:]] | *[!0-9]\]* | \[*\[* | *\]*\]* )
return 1;; # false
\[*[0-9]*\]* )
return 0;; # true
*)
return 1;; # false
esac
我在我的 Bash 脚本之一中使用了 =~
。但是,我需要使脚本与不支持该运算符的 Bash 版本兼容,特别是 msysgit which is not build against libregex 附带的 Bash 版本。我有一个使用 expr match
的解决方法,但由于某种原因,它在 Mac OS X 上再次不起作用。
因此,我只想使用 expr match
if [ -n "$MSYSTEM" -a ${BASH_VERSINFO[0]} -lt 4 ]
,否则使用 =~
。问题是 Bash 似乎总是解析整个脚本,即使 msysgit Bash 会在运行时执行解决方法,它在解析脚本时仍然会偶然发现 =~
。
是否可以根据 Bash 版本在同一脚本中有条件地执行代码,或者我应该寻找另一种方法来解决这个问题?
我目前的解决方案是在所有平台上使用 grep -q
。这避免了任何条件或复杂的代码结构。
可能仅在运行时使用 eval
来解析包含 =~
的代码也可行,但话又说回来,这会使代码更难阅读。
对于您的情况,您可以用等效的模式匹配替换正则表达式。
[[ $foo = \[+([0-9])\][[:space:]]* ]]
一些解释:
模式与整个字符串匹配。以下正则表达式和模式是等效的:
^foo$
和foo
^foo
和foo*
foo$
和*foo
foo
和*foo*
+(...)
匹配封闭模式的一次或多次出现,在本例中为[0-9]
。也就是说,如果$pattern
和$regex
匹配相同的字符串,那么+($pattern)
和($regex)+
.
对于这个特定的模式,可以阐明等效但可移植的 case
语句。不过,它需要有相当多的不同 glob 模式来枚举所有极端情况。
case $foo in
[![]* | \[[!0-9]* | *[!][0-9[:space:]]* | *[!0-9[:space:]] | \
*\]*[![:space:]] | *[!0-9]\]* | \[*\[* | *\]*\]* )
return 1;; # false
\[*[0-9]*\]* )
return 0;; # true
*)
return 1;; # false
esac