Reputation: 65
In JS, I can use a function String.prototype.replace() when replacing a submatch in a regular expression. For example:
var x = 'a1b2c3'.replace(/(\d+)/g, (num) => {
return num*num+1
})
console.log(x)
// 'a2b5c10'
I've tried using sed
but it seems that invoking an operator $(())
inside of the replacement is not possible.
$ echo "a1b2c3" | sed 's/\([^0-9]*\)\([0-9]\)\([^0-9]*\)/\1$((\2*\2+1))\3/g'
# Output: a$((1*1+1))b$((2*2+1))c$((3*3+1))
Is there a similar tool or function in bash
that has the functionality similar to JS's String.replace()
?
Upvotes: 4
Views: 330
Reputation: 85780
The bash
shell does support a native regex operator which you can enable with the ~
flag. All you need to do is define a regex, take the captured groups and replace them with the modified values
str='a1b2c3'
re='^.*([0-9]+).*([0-9]+).*([0-9]+).*$'
if [[ $str =~ $re ]]; then
for match in "${BASH_REMATCH[@]}"; do
final="${str/$match/$((match*match+1))}"
done
fi
printf '%s\n' "$final"
The [[ $str =~ $re ]]
does the regex match and updates the captured group array ${BASH_REMATCH[@]}
. So for each of the element in the order of their appearance, we do the string substitution operator ${str/old/new}
. The replacement value in your case is the number multiplied with itself and added by 1.
Add more capturing groups to the regex .*([0-9]+)
for subsequent matches.
If not for a pure bash
solution above, using an external utility like perl
, one could do it as
perl -pe 's/\d+/$&*$&+1/ge' <<<"$str"
The $&
refers to the captured digit in the string and the e
flag allows do arithmetic operations over the captured groups.
Upvotes: 1
Reputation: 50785
You can implement this in gawk using match()
and substr()
.
echo "a1b2c3" | awk '{
head = ""
tail = $0
while (match(tail, /[0-9]+/)) {
num = substr(tail, RSTART, RLENGTH)
num = num * num + 1
head = head substr(tail, 1, RSTART-1) num
tail = substr(tail, RSTART + RLENGTH)
}
print head tail
}'
Output
a2b5c10
Upvotes: 1