Case Scenerio:
Variable or Array
var=( 002.20 20.020 20.002000 00200 20.02 .020)
for f in ${var[@]}; do echo ${f}; done
Output: 2.2 20.02 20.002 200 20.02 .02
Trying to achive this using pure bash that with help of $BASH_REMATCH capture groups
Tried:
eg.
f=20.0000210
[[ $f =~ ([0-9]?\.?0?[1-9]?)(0*$) ]]
echo ${BASH_REMATCH[@]}
210 21 0
Expected:
echo ${BASH_REMATCH[@]
20.000021 0
Can anyone help with this. Please. After debugging it seems bash capture groups are behaving unusually. I dont know how BASH_REMATCH works but from online tutorials i have seen that using () we can split string into BASH_REMATCH array. But something odd with splitting
oK after some debugging it appears unusual behaviour is due to cygwin bash. eg var=0002; echo ${var##0} or echo ${var## (0)} doesnt work as expected
CodePudding user response:
Another way: (Another Use Case: Below Method will help splitting a string based on delimeter)
var=( 002.20 20.020 20.002000 00200 20.02 .020)
for f in ${var[@]}; do
[[ $f =~ (^[^\.?]*.)(.*) ]];
INT=$(echo ${BASH_REMATCH[1]});
FRAC=$(echo ${BASH_REMATCH[2]});
echo "$f --> ${INT## (0)}${FRAC%% (0)}"; done
Output
002.20 --> 2.2
20.020 --> 20.02
20.002000 --> 20.002
00200 --> 200
20.02 --> 20.02
.020 --> .02
Splits and captures the Integer part and Fractional Part
Capture 1 - (^[^.?].) --> Matches beginning to decimal point which is optional in case of natural numbers and append "." to result
Capture 2 - (.) --> Fractional part
Using BASH_REMATCH[1] & [2], stores integer in INT and Fraction in FRAC
Using string expansion remove leading "0" from INT and trailing "0" from FRAC
CodePudding user response:
If you want to use [[ var =~ REGEX ]]
and then BASH_REMATCH
, you can do:
#!/bin/bash
var=( 002.20 20.020 20.002000 00200 20.02 .020)
for i in "${var[@]}"; do # loop over each element in array
if [[ $i =~ "." ]]; then # does it contain '.'?
[[ $i =~ ^0*(.*[^0] )0*$ ]] # use regex to trim both ends
else
[[ $i =~ ^0*([^0] .*$) ]] # otherwise trim from front.
fi
echo ${BASH_REMATCH[1]} # output result
done
Example Output
2.2
20.02
20.002
200
20.02
.02
You can change echo
as needed to output with printf
for line control as desired.
CodePudding user response:
Using a regular expression approach in bash:
var=(002.20 20.020 20.002000 00200 20.02 .020 20.0000210)
# regex may match an empty string also
re='^0*([1-9][0-9]*)?(\.[0-9]*[1-9])?0*$'
for n in "${var[@]}"; do
[[ $n =~ $re ]] && echo "$n => ${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
done
Output:
002.20 => 2.2
20.020 => 20.02
20.002000 => 20.002
00200 => 200
20.02 => 20.02
.020 => .02
20.0000210 => 20.000021
RegEx Details:
^
: Start0*
: Match 0 or more zeroes([1-9][0-9]*)?
: Capture group #1 (optional) to match digit 1-9 followed by 0 or more of any digits(\.[0-9]*[1-9])?
: Capture group #2 (optional) to match dot then 0 or more of any digits then digit 1-90*
: Match 0 or more zeroes$
: End- In substitution we only keep values captured in capture group #1 and #2 ignoring leading and trailing zeroes.
CodePudding user response:
$ shopt -s extglob
$ var=( 002.20 20.020 20.002000 00200 20.02 .020 )
$ for f in "${var[@]## (0)}"; do
[[ "$f" =~ \. ]] && f="${f%% (0)}"
printf '%s\n' "$f"
done
2.2
20.02
20.002
200
20.02
.02
CodePudding user response:
You can do it via sed.
$ var=( 002.20 20.020 20.002000 00200 20.02 .020)
$ for f in ${var[@]}; do echo $(echo $f|sed -r 's/^0 |0 $//g'); done
2.2
20.02
20.002
2
20.02
.02