Pass the matched value to the function and replace the return value
How do I get Bash to match the regex, but instead of replacing the value with a constant string, it will instead pass the corresponding value to the function and then get the value to replace with the return value of the function.
Something like the following pseudocode, which replaces each match [a-d]
with the same character, but in uppercase:
function uppercase() { echo ${1^^}; }
string="abcdefgh123cbazyz"
echo ${string//[a-d]/uppercase()}
# output: ABCDef123CBAzyz
I am not proprietary, any language that is usually installed on a Unix system (for example sed
, awk
or even the limited regex support built into it bash
) can be used.
source to share
Bash cannot use user-defined functions inside a parameter extension .
To accomplish what you want, use case-modification pattern matching :
string="abcdefgh123cbazyz"
echo ${string^^[a-d]}
Output:
ABCDefgh123CBAzyz
source to share
You can use Perl for this:
perl -lape 's/([a-d])/`uppercase $1`/eg' <<< "$string"
but this would require an executable script named uppercase
. Perl flag e
(eval) executed the command in a match when there is a match.
Another way via sed:
function uppercase() {
echo ${1^^}
}
export -f uppercase
string="abcdefgh123cbazyz"
echo "echo $(sed 's/\([a-d]\)/$(uppercase \1)/g' <<< "$string")" | sh
source to share
Use tr
:
echo abcdefgh123cbazyz | tr '[a-d]' '[A-D]'
Or sed
:
echo abcdefgh123cbazyz | sed -r 's|[a-d]|\U&|g'
Output:
ABCDefgh123CBAzyz
Update
Callback with Ruby
:
puts "abcdefgh123cbazyz".gsub(/[a-d]/){ |m| m.upcase }
Callbak with Python
:
import re
s = "abcdefgh123cbazyz"
def repl(m):
return m.upper()
print(re.sub('\[\[:(.+?):\]\]', repl, s))
Callback with Perl
:
my $s = "abcdefgh123cbazyz";
$s =~ s/([a-d])/uc($1)/eg;
print "${s}\n";
Output:
ABCDefgh123CBAzyz
source to share
In Perl, you can grab a group and pass it to a subroutine like this using the flag e
:
perl -pe 'sub callback { return uc $_[0] } s/([a-d])/callback $1/eg' <<<"$string"
Result for your string:
ABCDefgh123CBAzyz
Here I just introduced my own wrapper around an existing function uc
that returns converts letters to uppercase. You can change the body of the routine to do whatever you want.
source to share
FWIW this is how you would do it in GNU awk (for the 4th argument to split ()):
$ cat tst.awk
function uppercase(str) { return toupper(str) }
{
split($0,flds,/[a-d]/,seps)
for (i=1;i in flds; i++) {
printf "%s%s", flds[i], uppercase(seps[i])
}
print ""
}
$ echo "abcdefgh123cbazyz" | gawk -f tst.awk
ABCDefgh123CBAzyz
or with any awk:
$ cat tst.awk
function uppercase(str) { return toupper(str) }
{
while ( match($0,/[a-d]/) ) {
printf "%s%s", substr($0,1,RSTART-1), uppercase(substr($0,RSTART,RLENGTH))
$0 = substr($0,RSTART+RLENGTH)
}
print
}
$ echo "abcdefgh123cbazyz" | awk -f tst.awk
ABCDefgh123CBAzyz
source to share