0

我目前正在尝试从例如看起来像这样的文本中提取所有匹配的表达式并将它们放入数组中。

aaaaaaaaa${bbbbbbb}ccccccc${dddd}eeeee
ssssssssssssssssss${TTTTTT}efhsekfh ej
348653jlk3jß1094utß43t59ßgöelfl,-s-fko

匹配表达式与此类似:${}. 请注意,我需要完整的表达,而不仅仅是这个表达之间的单词!所以在这种情况下,结果应该是一个数组,其中包含:

${bbbbbbb}
${dddd}
${TTTTTTT}

我偶然发现但无法解决的问题:

  1. 它不应该将其视为一个整体 ${bbbbbbb}ccccccc${dddd},而是每个人都有自己的
  2. grep -o 没有安装在旧机器上,Perl 也不允许!
  3. 许多命令,例如 BASH_REMATCH 只提供整行或表达式的第一次出现,而不是行中所有匹配的表达式!

提到的模式\${[^}]*}似乎部分起作用,因为它可以提取表达式的第一次出现,但是如果它在同一文本行中,它总是会忽略之后的那些。我需要的是在该行中找到的所有匹配表达式,而不仅仅是第一个。

4

2 回答 2

1

您可以将字符串拆分为任何字符$, {, }:

$ s='...blaaaaa${blabla}bloooo${bla}bluuuuu...'
$ echo "$s"
...blaaaaa${blabla}bloooo${bla}bluuuuu...
$ IFS='${}' read -ra words <<< "$s"
$ for ((i=0; i<${#words[@]}; i++)); do printf "%d  %s\n" $i "${words[i]}"; done
0  ...blaaaaa
1  
2  blabla
3  bloooo
4  
5  bla
6  bluuuuu...

因此,如果您尝试提取大括号内的单词:

$ for ((i=2; i<${#words[@]}; i+=3)); do printf "%d  %s\n" $i "${words[i]}"; done
2  blabla
5  bla

如果上述内容不适合您,则 grep 将起作用:

$ echo '...blaaaaa${blabla}bloooo${bla}bluuuuu...' | grep -o '\${[^}]\+}'
${blabla}
${bla}

你还没有确切地告诉我们你想要什么输出。

于 2013-06-24T20:06:17.580 回答
0

因为它困扰了我很多,所以我直接在 www.unix.com 上询问,并得到了适合我古老外壳的解决方案。因此,如果有人遇到同样的问题,这里的解决方案是:

line='aaaa$aa{yyy}aaa${important}xxxxxxxx${important2}oo{o$}oo$oo${importantstring3}'
IFS=\$ read -a words <<< "$line" 
regex='^(\{[^}]+})'
for e in "${words[@]}"; do
    if [[ $e =~ $regex ]]; then 
        echo "\$${BASH_REMATCH[0]}";
    fi;
done

然后打印以下内容 - 甚至不会受到语法正确表达式的随机出现${或之间的干扰:}

${important}
${important2}
${importantstring3}

在从论坛获得另一个更新后,我已经更新了完整的解决方案:现在它也忽略了这个:aaa$aa{yyy}aaaa- 它以前打印为 ${yyy} - 但它应该完全忽略,因为 and 之间有$字符{。现在,通过在正则表达式开头的附加锚定,它可以按预期工作。

我刚刚发现了另一个问题:理论上使用上述方法,如果读取的行看起来像这样,我仍然会得到错误的输出line='{ccc}aaaa${important}aaa'。IFS 会拆分它,而 REGEX 会匹配,尽管前面{ccc}没有符号。$这是次优的。
然而,以下方法可以解决它:在获得 BASH_REMATCH 之后,我需要在原始行中进行搜索 - 我给 IFS 的那个 - 对于这个确切的表达式${ccc}- 不同的$是,包含在内!只有当它找到这个完全匹配时,它才算作有效匹配;否则它应该被忽略。一种反向搜索方法...

更新 - 添加此反向搜索以忽略行首的陷阱:

pattern="\$${BASH_REMATCH[0]}";
searchresult="";
searchresult=`echo "$line" | grep "$pattern"`;

if [ "$searchresult" != "" ]; then echo "It was found!"; fi;

可忽略的问题:如果该行看起来像这样line='{ccc}aaaaaa${ccc}bbbbb',它会将 {ccc}一个识别为有效匹配(尽管不是)并打印它,因为反向搜索找到了第二个 ${ccc}。尽管这不是故意的,但与我的特定目的无关,因为它暗示这种模式实际上在同一行中至少存在一次。

于 2013-06-25T12:17:30.753 回答