2012-03-07 43 views
36

虽然我几乎可以肯定这已经覆盖了,我似乎无法找到具体到这样的东西。当我继续我的学习狂欢的旅程时,我一直在寻找令我感到困惑的部分,为什么事情会以他们的方式发生。使用匹配查找字符串中的子只庆典

搜索并替换或只是字符串匹配的子字符串是最有可能的编写脚本时,你首先要做的事情之一。但是,试图坚持单一语言或一组工具在ba​​sh中很难做到,因为您可以通过多种方式解决大多数问题。我正尽我所能,尽量保持尽可能低的水平与bash。我遇到了一个麻烦,我需要有人向我解释。

这样子串与匹配的bash搜索给了我不同的结果取决于正则表达式我用,我不知道为什么。

#!/bin/bash 
Stext="Hallo World" 
echo `expr "$Stext" : '^\(.[a-z]*\)'` # Hallo 
echo `expr "$Stext" : '.*World'`  # 11 

虽然这两个搜索词,我认为,既没有返回他们所发现。为什么?

回答

23

两个表达式是等价的,所不同的是使用正则表达式:

$ echo `expr "$Stext" : '^\(.[a-z]*\)'` 
Hallo 
$ echo `expr "$Stext" : '^.[a-z]*'` 
5 
$ echo `expr "$Stext" : '\(.*World\)'` 
Hallo World 
$ echo `expr "$Stext" : '.*World'` 
11 

正如你所看到的,括号是什么让差异要么返回比赛或比赛本身的长度。

您可以在高级Bash脚本编程指南Chapter 10找到更多的例子。

+0

感谢简单的解释@jcollado :)我用你提供的文档,但不知何故没有得到这个括号功能。 Bash脚本指南不太容易消化。 – 2012-03-07 08:21:31

+1

由于这个问题是关于[tag:bash],所以更喜欢使用* builtin * regex作为[@kev建议](http://stackoverflow.com/a/9602260/1765658)而不是* fork到'/ usr/bin/expr' *! – 2015-02-27 23:05:29

49

可以使用BASH_REMATCH变量bash得到匹配的字符串:

$ Stext="Hallo World" 
$ [[ $Stext =~ ^.[a-z]* ]] && echo $BASH_REMATCH 
Hallo 
$ [[ $Stext =~ ^(.[a-z]*) ]] && echo ${BASH_REMATCH[1]} 
Hallo 

子字符串的正则表达式中的括号内的子表达式匹配的保存在数组变量BASH_REMATCH。索引为0的BASH_REMATCH元素是匹配整个正则表达式的字符串部分。索引为n的BASH_REMATCH元素是匹配第n个加括号的子表达式的字符串部分。

+0

...和'[[“Hello world”=〜^ [^ \] *]] && echo $ {#BASH_REMATCH}' - >'5' ... – 2015-02-27 23:02:31

0

我做这个简单的功能:

match() { 
    TRUE=1 
    FALSE=0 
    match_return=0 
    echo $1 | grep $2 >/dev/null 
    [ $? -eq 0 ] && match_return=$TRUE || match_return=$FALSE 
} 

用法:

match Testing Test ; [ $match_return -eq 1 ] && echo "match!" || echo "nope" 

整个代码:https://gist.github.com/TeeBSD/5121b3711fad40a09455

+0

这篇文章与问题或答案没有实际相关性。 – 2015-03-16 12:32:59

0

为了快速字符串搜索......一个选项是grep的。
如果没有找到,返回空,否则匹配:

found=`echo $big | grep -e $short` 

if [ ! -z $found ]; then echo 'There is a match'; else echo 'No no'; fi