因为它困扰了我很多,所以我直接在 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}
。尽管这不是故意的,但与我的特定目的无关,因为它暗示这种模式实际上在同一行中至少存在一次。