Issue
I want to make a program editing file code with shell programming
there is command 'Remove ${} in arithmetic expansion$(())' and I have a problem in implementation.
I'm going to make bash shell code below
cnt=$(( ${cnt} + ${cnt123} ))
to
cnt=$(( cnt + cnt123 ))
I want to remove command substitution bracket in arithmetic Expansion bracket
I tried to do with this regex expression:
sed -Ei 's/(\$\(\()([^\)]*?)\$\{([^\}]+?)\}(.*?)(\)\))/\1\2\3\4\5/g' $file
but, it just found a longest one.(even though there are another match before matched one)
if you want to see visualized regex expression, click this link visualized image
result showed like this:
cnt=$(( ${cnt} + cnt123 ))
How to do remove internal bracket in nested bracket? (I should just use awk or sed, but if it could be impossible, it doesn't matter using other bash command)
works example:
s=$(( ${s} ** 2 ))
to
s=$(( s ** 2 ))
sum=$(( ${a} + ${b} ))
to
sum=$(( a + b ))
echo $(( (${var} * ${var2}) / ${var3} ))
to
echo $(( (var * var2) / var3 ))
echo ${d} $((${t1} + ${t2})) ${e}
to
echo ${d} $(( t1 + t2 )) ${e}
:my sample input file (it doesn't matter what it do for)
#! /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
Solution
As it is not an easy task for sed/awk regex and relevant functions,
please let me show a perl
solution, although perl
is not tagged in
your question.
perl -i -pe 's/(?<=\$\(\().+?(?=\)\))/ $_ = $&; s#\$\{(.+?)}#$1#g; $_ /ge' "$file"
Input file example:
s=$(( ${s} ** 2 ))
sum=$(( ${a} + ${b} ))
echo $(( (${var} * ${var2}) / ${var3} ))
echo ${d} $((${t1} + ${t2})) ${e}
Modified result:
s=$(( s ** 2 ))
sum=$(( a + b ))
echo $(( (var * var2) / var3 ))
echo ${d} $((t1 + t2)) ${e}
- The perl substitution
s/pattern/expression/e
replaces the matchedpattern
with the perlexpression
instead of literal (or fixed) replacement. You can perform a dynamic replacement with this mechanism. (?<=\$\(\().+?(?=\))
matches a substring which is preceded by$((
and followed))
. Then the matched substring will be the content within$(( .. ))
. The perl variable$&
is assigned to it.- The expression
$_ = $&; s#\$\{(.+?)}#$1#g; $_
is a perl code to remove the paired${
and}
from the matched substring above. Theg
option after the delimiter#
works as that ofsed
.
Answered By - tshiono Answer Checked By - Senaida (WPSolving Volunteer)