You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用sed移除算术扩展$(( ))中的嵌套${}括号?

移除算术扩展$(( ))中的${}的Shell实现方案

需求与问题

需要编写Shell工具实现:移除算术扩展$(( ... ))结构内的变量引用括号${},将如cnt=$(( ${cnt} + ${cnt123} ))的代码转换为cnt=$(( cnt + cnt123 )),同时支持嵌套括号内的替换(比如echo $(( (${var} * ${var2}) / ${var3} ))需转为echo $(( (var * var2) / var3 )))。

此前尝试的sed命令仅能匹配并替换单次目标,无法处理同一$(( ))内的多个${},例如执行sed -Ei 's/(\$\(\()([^\)]*?)\$\{([^\}]+?)\}(.*?)(\)\))/\1\2\3\4\5/g' $file后,仅能替换最后一个${cnt123},剩余${cnt}未被处理。

解决方案

方法1:使用sed循环替换

利用sed的标签循环功能,重复执行替换直到所有目标都被处理:

sed -Ei ':loop; s/(\$\(\([^)]*)\$\{([^}]+)\}([^)]*\)\))/\1\2\3/g; t loop' "$file"
  • :loop:定义循环标签
  • 正则匹配$(( ... ))内的${xxx},将其替换为xxx
  • t loop:如果本次替换成功,回到标签继续执行,直到无匹配项

方法2:使用Perl一行命令

Perl的正则支持更灵活的循环替换,代码更简洁:

perl -pi -e 'while (s/\$\(\((.*?)\$\{([^}]+)\}(.*?)\)\)/$(( $1$2$3 ))/g) {}' "$file"
  • while (s/.../.../g):循环执行替换,直到没有可匹配的${}

验证示例

以下测试用例均可被正确转换:

  • s=$(( ${s} ** 2 )) → s=$(( s ** 2 ))
  • sum=$(( ${a} + ${b} )) → sum=$(( a + b ))
  • echo $(( (${var} * ${var2}) / ${var3} )) → echo $(( (var * var2) / var3 ))
  • echo ${d} $((${t1} + ${t2})) ${e} → echo ${d} $(( t1 + t2 )) ${e}

样本文件处理结果

原样本输入中的行cnt=$(( ${cnt}+ ${cnt123} ))会被转换为cnt=$(( cnt+ cnt123 )),处理后的完整代码如下:

#! /bin/bash

cnt=0
cnt123=1
for filename in *
do
        fname=$(basename $filename)
        cname=$(echo $fname | tr A-Z a-z)
        if [ "$fname" !=  "$cname" ] 
        then
                if [ -e "$cname" ]
                then 
                   echo "$cname already exists"
                   exit 1
                fi
                echo "$fname is renamed $cname"
                mv $fname $cname
                cnt=$(( cnt+ cnt123 ))
        fi
done
echo "Total count: $cnt"
exit 0

内容的提问来源于stack exchange,提问作者Seung Yun Baek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 03:35:22