linux shell:提取正则表达式捕获组(catch group)匹配的字符串

Posted 10km

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux shell:提取正则表达式捕获组(catch group)匹配的字符串相关的知识,希望对你有一定的参考价值。

bash

目前大部分shell(如bash)都提供了正则表达式判断操作符=~,如下就可以对一个字符符判断是否匹配正则表达式:

$ [[ "hello world" =~ wor(ld)? ]] && echo matched
matched

其实基于上面的表达式不仅可以判断是否匹配正则表达,还可以通过上面表达式创建的变量 BASH_REMATCH(数组)提取捕获组(catch group),
如下提取一个url的protocol和host部分

$ [[ "http://www.baidu.com" =~ (https?)://([[:alnum:]]+(\\.[[:alnum:]_]+)*)  ]]  \\
&& echo $BASH_REMATCH[1] $BASH_REMATCH[2]
http www.baidu.com

$BASH_REMATCH[0] 即正则表达式的捕获组0(全部字符串)
$BASH_REMATCH[1] 即正则表达式的捕获组1,以此类推

BASH_REMATCH 是 bash定义的保存正则表达式捕获组的变量,不同的脚本解释有不同的定义,比如zsh,ksh就有另外的变量定义方式

ksh

保存正则表达匹配数据的数组变量名叫 .sh.match ,对BASH_REMATCH,引用时必须以$.sh.match方式引用

$.sh.match[0] 即正则表达式的捕获组0(全部字符串)
$.sh.match[1] 即正则表达式的捕获组1,以此类推

zsh

$MATCH 保存匹配的整个字符串,对应就是bash的BASH_REMATCH[0]
$match保存捕获组数据的数组(索引从1开始),$match[1]就对应BASH_REMATCH[1]

通用的实现

根据上面不同shell的实现试可以合成实现一个通用函数来以抹平shell之间的差异

function reMatch 
  typeset ec
  unset -v reMatch # initialize output variable
  [[ $1 =~ $2 ]] # perform the regex test
  ec=$? # save exit code
  if [[ $ec -eq 0 ]]; then # copy result to output variable
    [[ -n $BASH_VERSION ]] && reMatch=( "$BASH_REMATCH[@]" )
    [[ -n $KSH_VERSION ]]  && reMatch=( "$.sh.match[@]" )
    [[ -n $ZSH_VERSION ]]  && reMatch=( "$MATCH" "$match[@]" )
  fi
  return $ec


调用示例:

$ reMatch "http://www.baidu.com" "(https?)://([[:alnum:]]+(\\.[[:alnum:]_]+)*)"
$ echo $reMatch[1] $reMatch[2]
http www.baidu.com

更详细的说明参见参考资料1

参考资料


  1. 《retrieve a word after a regular expression in shell script》 ↩︎

以上是关于linux shell:提取正则表达式捕获组(catch group)匹配的字符串的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式 1. 分组提取/非捕获组

具有多个捕获组的 R 中的正则表达式组捕获

正则表达式 c# 获取捕获组的子组

正则表达式组捕获[重复]

如何使用正则表达式验证捕获组中的最后一个字符

如何在 linux shell 中使用正则表达式从文件中提取 IP 地址?