Shell里内置数组BASH_REMATCH[n]个人解析
2015-05-26 14:22
92 查看
先引用一段资料,出自:http://bbs.chinaunix.net/thread-4125147-1-1.html
红色注释为个人添加
--------------------------------------------------------------搬运内容分割线----------------------------------------------------------------
从 bash 3以上版本里,已经自带正则匹配的功能, 很多情况下,可以不用awk/sed来做。 比如这个需求:
<List>
<Job id="1" name="abc"/>
<Job id="2" name="zyz"/>
<Job id="3" name="beew"/>
</List>
复制代码
想要得到这个结果。
abc | 1
zyz | 2
beew | 3
复制代码
我们用纯shell的方法。
#!/bin/bash
while read line; do //读入变量line
if [[ $line =~ id=\"([0-9]+).*name=\"([^\"]*) ]]; then
//子模式1为([0-9]+);子模式2为([^\"]*)
echo "${BASH_REMATCH[2]} | ${BASH_REMATCH[1]}"
fi
done < file
复制代码
如果你对sed 里的 \1 \2 的用法很熟的话,就应该很快的明白 BASH_REMATCH[1] 和 BASH_REMATCH[2] 代表了什么。
把楼下@rogantianwz的回复帖在这里,解释的很不错。
双目运算符=~;它和==以及!=具有同样的优先级。如果使用了它,则其右边的字符串就被认为是一个扩展的正则表达式来匹配。如果字符串和模式匹配,则返回值是0,否则返回1。如果这个正则表达式有语法错误,则整个条件表达式的返回值是2。如果打开了shell的nocasematch 选项则匹配时不考虑字母的大小写。模式的任何部分都可以被引用以强制把其当作字符串来匹配。由正则表达式中括号里面的子模式匹配的字符串被保存在数组变量BASH_REMATCH 中。BASH_REMATCH 中下标为0的元素是字符串中与整个正则表达式匹配的部分。BASH_REMATCH
中下标为n的元素是字符串中与第n 个括号里面的子模式匹配的部分。
--------------------------------------------------------------搬运内容分割线----------------------------------------------------------------
我的理解:子模式1为匹配出现一次或多次(+号的作用)任意0~9字符;子模式2为出现零次或多次(*号的作用)的非双引号"字符,其中[^\"]取一切非双引号单个字符,反斜杠\用来转义双引号"。接下来的echo "${BASH_REMATCH
}"中,按照先读取匹配子模式2的数组内容BASH_REMATCH{2},即上例中的abc,xyz,beew等等,接着打印竖线|,最后读取匹配子模式1的数组内容,即1,2,3。
下面搬运一个匹配ip地址的脚本
出处:http://www.yunweipai.com/archives/4660.html
--------------------------------------------------------------搬运内容分割线----------------------------------------------------------------
在运维场景下,我们经常需要在服务器上用正则表达式来匹配IP地址。
shell和其它编程语言一样,也可以使用正则分组捕获,不过不能使用 $1或\1这样的形式来捕获分组,可以通过数组${BASH_REMATCH}来获得,如${BASH_REMATCH[1]},${BASH_REMATCH
}
下面以ip="121.0.2.2"为例,shell脚本代码如下(当然,你要做成更通用交互式的脚本,可以通过expect来实现):
#!/bin/bash
ip="121.0.2.2"
if [[ $ip =~ ^([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$ ]]
then
echo "Match"
echo ${BASH_REMATCH[1]}
echo ${BASH_REMATCH[2]}
echo ${BASH_REMATCH[3]}
echo ${BASH_REMATCH[4]}
else
echo "Not match"
fi
--------------------------------------------------------------搬运内容分割线----------------------------------------------------------------
我的分析:
如果符合ip地址定义范围,则返回结果为
Match
121
0
2
2
否则返回Not match(运行结果已实机验证)
if判断语句里的正则表达式[0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5]意为匹配符合ip地址定义原则的字段:当总位数为1~2时,符合要求的取值为0~99,当总位数为3的时候,符合的取值区间为100~199,200~249,250~255,其中竖线 | 的作用是或逻辑运算
红色注释为个人添加
--------------------------------------------------------------搬运内容分割线----------------------------------------------------------------
从 bash 3以上版本里,已经自带正则匹配的功能, 很多情况下,可以不用awk/sed来做。 比如这个需求:
<List>
<Job id="1" name="abc"/>
<Job id="2" name="zyz"/>
<Job id="3" name="beew"/>
</List>
复制代码
想要得到这个结果。
abc | 1
zyz | 2
beew | 3
复制代码
我们用纯shell的方法。
#!/bin/bash
while read line; do //读入变量line
if [[ $line =~ id=\"([0-9]+).*name=\"([^\"]*) ]]; then
//子模式1为([0-9]+);子模式2为([^\"]*)
echo "${BASH_REMATCH[2]} | ${BASH_REMATCH[1]}"
fi
done < file
复制代码
如果你对sed 里的 \1 \2 的用法很熟的话,就应该很快的明白 BASH_REMATCH[1] 和 BASH_REMATCH[2] 代表了什么。
把楼下@rogantianwz的回复帖在这里,解释的很不错。
双目运算符=~;它和==以及!=具有同样的优先级。如果使用了它,则其右边的字符串就被认为是一个扩展的正则表达式来匹配。如果字符串和模式匹配,则返回值是0,否则返回1。如果这个正则表达式有语法错误,则整个条件表达式的返回值是2。如果打开了shell的nocasematch 选项则匹配时不考虑字母的大小写。模式的任何部分都可以被引用以强制把其当作字符串来匹配。由正则表达式中括号里面的子模式匹配的字符串被保存在数组变量BASH_REMATCH 中。BASH_REMATCH 中下标为0的元素是字符串中与整个正则表达式匹配的部分。BASH_REMATCH
中下标为n的元素是字符串中与第n 个括号里面的子模式匹配的部分。
--------------------------------------------------------------搬运内容分割线----------------------------------------------------------------
我的理解:子模式1为匹配出现一次或多次(+号的作用)任意0~9字符;子模式2为出现零次或多次(*号的作用)的非双引号"字符,其中[^\"]取一切非双引号单个字符,反斜杠\用来转义双引号"。接下来的echo "${BASH_REMATCH
}"中,按照先读取匹配子模式2的数组内容BASH_REMATCH{2},即上例中的abc,xyz,beew等等,接着打印竖线|,最后读取匹配子模式1的数组内容,即1,2,3。
下面搬运一个匹配ip地址的脚本
出处:http://www.yunweipai.com/archives/4660.html
--------------------------------------------------------------搬运内容分割线----------------------------------------------------------------
在运维场景下,我们经常需要在服务器上用正则表达式来匹配IP地址。
shell和其它编程语言一样,也可以使用正则分组捕获,不过不能使用 $1或\1这样的形式来捕获分组,可以通过数组${BASH_REMATCH}来获得,如${BASH_REMATCH[1]},${BASH_REMATCH
}
下面以ip="121.0.2.2"为例,shell脚本代码如下(当然,你要做成更通用交互式的脚本,可以通过expect来实现):
#!/bin/bash
ip="121.0.2.2"
if [[ $ip =~ ^([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$ ]]
then
echo "Match"
echo ${BASH_REMATCH[1]}
echo ${BASH_REMATCH[2]}
echo ${BASH_REMATCH[3]}
echo ${BASH_REMATCH[4]}
else
echo "Not match"
fi
--------------------------------------------------------------搬运内容分割线----------------------------------------------------------------
我的分析:
如果符合ip地址定义范围,则返回结果为
Match
121
0
2
2
否则返回Not match(运行结果已实机验证)
if判断语句里的正则表达式[0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5]意为匹配符合ip地址定义原则的字段:当总位数为1~2时,符合要求的取值为0~99,当总位数为3的时候,符合的取值区间为100~199,200~249,250~255,其中竖线 | 的作用是或逻辑运算
相关文章推荐
- Linux基础学习之bash shell内置命令----type
- linux bash Shell脚本经典之Fork炸弹解析:() { :|:& };:
- linux shell bash 内置变量参考
- linux shell bash 内置变量参考
- 脚本、shell、shell脚本、bash的个人理解
- shell学习之常用bash内置变量
- bash shell之数组使用
- Linux操作系统基础解析之(七)——Bash(Shell)基础知识(4)
- linux shell bash 内置变量参考
- Zsh vs. Bash不完全对比解析,zsh是一种更强大的被成为“终极”的Shell
- bash shell关联数组提高查找效率
- Linux操作系统基础解析之(七)——Bash(Shell)基础知识(5)
- Linux操作系统基础解析之(七)——Bash(Shell)基础知识(1)
- Zsh vs. Bash不完全对比解析,zsh是一种更强大的被成为“终极”的Shell
- bash shell关联数组提高查找效率
- Linux操作系统基础解析之(七)——Bash(Shell)基础知识(6)
- bash shell 学习 —— 数组
- Bashe Shell之数组及bash配置文件解析
- bash shell 学习 —— 数组
- bash shell之数组使用(牛逼篇)