怎么做"或"在bash的子字符串匹配中

时间:2014-11-13 12:46:18

标签: regex bash shell substring

echo `expr "hello" : '\(hi|hello\)'`
echo `expr "hi" : '\(hi|hello\)'`

显然我正在尝试匹配“hello”然后“hi”与regex hello和hi匹配,但两者都不匹配。

我该怎么表达呢?

4 个答案:

答案 0 :(得分:3)

或者,简单的球体

case $str in
    *hi* | *hello*) echo "pleased to meet you"
esac

答案 1 :(得分:2)

在这个简单的情况下,最好的选择是使用extended globs而不是正则表达式(它会更有效率,让您免于头痛):

string=hello
if [[ $string = @(hi|hello) ]]; then
    echo "String matches"
fi

或者(正如你在标题中提到的子串匹配),

string="hello world"
if [[ $string = *@(hi|hello)* ]]; then
    echo "String matches"
fi

注意。使用[[结构,无需启用extglobreference manual specifies

  

当使用==!=运算符时,运算符右侧的字符串将被视为一种模式,并根据Pattern Matching中所述的规则进行匹配。

并且模式匹配中的规则描述了扩展的全局。

答案 2 :(得分:1)

expr的更现代的替代方法是使用Bash regular expressions

re='hi|hello'
string=hi
[[ $string =~ $re ]] && echo "$string matched"

答案 3 :(得分:1)

|字符在扩展正则表达式中可用,但expr仅使用带有:运算符的基本正则表达式。 [更新:至少在基本正则表达式的POSIX版本中;正如Glenn Jackman所指出的,expr hello '\(hello\|\hi\)'将与GNU expr一起工作。您需要将命令重写为对expr的两次单独调用:

$ expr hello : '\(hello\)' || expr hello : '\(hi\)'
hello
$ expr hi : '\(hello\)' || expr hi : '\(hi\)'

hi
$ expr foo : '\(hello\)' || expr foo : '\(hi\)'


$

这仍然不太理想,因为失败的匹配仍然输出一个空字符串。使用其他答案中提供的替代方案会好得多。特别是,case语句与POSIX兼容,不依赖于任何bash扩展名。

更新:虽然正则表达式本身无法使用|,但您可以在同一个:的调用中合并两个expr表达式:

expr hi : '\(hello\)' \| hi : '\(hi\)'

当第一个:找不到匹配项时,它会尝试第二个匹配项。这可以防止expr为失败的第一次匹配输出空字符串。