2012-01-03 112 views
5

我想分析类似于使用从击内正则表达式以下成独立变量字符串:可选参数

Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";attributes="occi.core.id occi.core.title"; 

Category: resource;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Resource";rel="http://schemas.ogf.org/occi/core#entity";attributes="occi.core.summary"; 

第一部分“标题”前对所有字符串都是通用的,部分标题和属性是可选的。

我设法提取所有字符串通用的必需参数,但我有不一定对所有字符串都存在的可选参数的问题。据我发现,Bash不支持我将用于此目的的非捕获括号。

这是我迄今取得:

CATEGORY_REGEX='Category:\s*([^;]*);scheme="([^"]*)";class="([^"]*)";' 
category_string='Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";attributes="occi.core.id occi.core.title";' 
[[ $category_string =~ $CATEGORY_REGEX ]] 
echo ${BASH_REMATCH[0]} 
echo ${BASH_REMATCH[1]} 
echo ${BASH_REMATCH[2]} 
echo ${BASH_REMATCH[3]} 

正则表达式我想用(以及在Ruby的工作对我来说)是:

CATEGORY_REGEX='Category:\s*([^;]*);\s*scheme="([^"]*)";\s*class="([^"]*)";\s*(?:title="([^"]*)";)?\s*(?:rel="([^"]*)";)?\s*(?:location="([^"]*)";)?\s*(?:attributes="([^"]*)";)?\s*(?:actions="([^"]*)";)?' 

有什么使用命令行工具解析字符串的其他解决方案,而不必回退到perl,python或ruby?

回答

6

我认为在bash正则表达式中不存在非捕获组,所以您的选择是使用脚本语言或从所有(?:...)组中删除?:,并且只需注意您引用的哪些组:

CATEGORY_REGEX='Category:\s*([^;]*);\s*scheme="([^"]*)";\s*class="([^"]*)";\s*(title="([^"]*)";)?\s*(rel="([^"]*)";)?\s*(location="([^"]*)";)?\s*(attributes="([^"]*)";)?\s*(actions="([^"]*)";)?' 
category_string='Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";attributes="occi.core.id occi.core.title";' 
[[ $category_string =~ $CATEGORY_REGEX ]] 
echo "full:  ${BASH_REMATCH[0]}" 
echo "category: ${BASH_REMATCH[1]}" 
echo "scheme:  ${BASH_REMATCH[2]}" 
echo "class:  ${BASH_REMATCH[3]}" 
echo "title:  ${BASH_REMATCH[5]}" 
echo "rel:  ${BASH_REMATCH[7]}" 
echo "location: ${BASH_REMATCH[9]}" 
echo "attributes: ${BASH_REMATCH[11]}" 
echo "actions: ${BASH_REMATCH[13]}" 

注意,开始我们需要每次跳过一组可选的参数,因为从4上的偶数编号的基团含有参数名以及所述值(如果该参数是本)。

+0

确实有效。这不是最优雅的解决方案,但只要bash中没有非捕获组,每次跳过组的解决方法可能是最佳解决方案。有一件事仍然困扰着我:如果分号后面有空格,则正则表达式会失败,即使在它们后面有“\ s *”模式来匹配空格。 – 2012-01-03 21:53:30

+0

看来,“\ s *”等特殊字符不起作用。尽管只用一个空格来替换它确实奏效:“\ s *”=>“*” – 2012-01-12 10:39:28

+0

尝试使用[[:space:]] *而不是\ s。 – 2015-11-18 15:00:44

0

可以使用正则表达式的神奇一点点模仿不匹配组在bash:

   _2__ _4__ _5__ 
[[ "[email protected]" =~ ((.+)@|)((.+)/|)(.+) ]]; 
echo "${BASH_REMATCH[2]:--} ${BASH_REMATCH[4]:--} ${BASH_REMATCH[5]:--}" 
# Output: fu - k 

人物@/是我们解析字符串的一部分。 Regexp管道|用于左侧或右侧(空)部件匹配。

为了好奇,${VAR:-<default value>}是在$ VAR为空的情况下具有默认值的可变扩展。

+0

这对我不起作用。我只得到三个破折号。 – Joeytje50 2017-08-29 23:32:25