我目前正在尝试从文本中提取所有匹配的表达式,例如看起来像这样,把它们放到一个数组中。
aaaaaaaaa${bbbbbbb}ccccccc${dddd}eeeee
ssssssssssssssssss${TTTTTT}efhsekfh ej
348653jlk3jß1094utß43t59ßgöelfl,-s-fko
匹配表达式与此类似:${}
。要注意我需要完整的表达,而不仅仅是这个表达式之间的单词!所以在这种情况下,结果应该是一个包含以下内容的数组:
${bbbbbbb}
${dddd}
${TTTTTTT}
我偶然发现并无法解决的问题:
${bbbbbbb}ccccccc${dddd}
但每个都是自己的所提到的模式\${[^}]*}
似乎部分起作用,因为它可以提取表达式的第一次出现,但是如果它在同一文本行中,它总是省略后面的那些。我需要的是在行中找到的所有匹配表达式,而不仅仅是第一个。
答案 0 :(得分: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}
你还没有告诉我们你想要的输出。
答案 1 :(得分: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} - 但它应该完全忽略,因为有字符在$
和{
之间。现在,在正则表达式的开头附加锚定它可以正常工作。
我刚刚发现另一个问题:理论上使用上述方法如果读取行看起来像line='{ccc}aaaa${important}aaa'
,我仍会得到错误的输出。 IFS将拆分它,REGEX将匹配{ccc}
,尽管前面没有$
符号。这不是最理想的
然而,下面的方法可以解决它:在获得BASH_REMATCH之后,我需要在原始行中进行搜索 - 我给IFS的那个 - 对于这个精确表达式${ccc}
- 区别于{{1 }} 已经包括了!并且只有当它找到这种完全匹配时,才会将其视为有效匹配;否则应该被忽略。一种反向搜索方法......
更新 - 添加此反向搜索以忽略行开头的陷阱:
$
可忽略的问题:如果该行看起来像pattern="\$${BASH_REMATCH[0]}";
searchresult="";
searchresult=`echo "$line" | grep "$pattern"`;
if [ "$searchresult" != "" ]; then echo "It was found!"; fi;
,它会将第一个 line='{ccc}aaaaaa${ccc}bbbbb'
识别为有效匹配(尽管不是)并打印出来,因为反向搜索找到了第二个 {ccc}
。虽然这并不意味着它与我的具体目的无关,因为它暗示这种模式实际上至少在同一行中存在一次。