将匹配的值传递给函数,并用返回值替换



如何让Bash匹配正则表达式,而不是用常量字符串替换值,而是将匹配的值传递给函数,然后从函数的返回值中获取要替换的值。

类似于下面的伪代码,它将[a-d]的每个匹配替换为相同的字符,但是大写:

function uppercase() { echo ${1^^}; }
string="abcdefgh123cbazyz"
echo ${string//[a-d]/uppercase()}
# output: ABCDef123CBAzyz

我并不特别,任何通常安装在Unix系统上的语言(例如sed, awk,甚至bash内置的有限正则表达式支持)都可以使用。

Bash不能在参数扩展中使用用户定义的函数

要完成你想要的,使用模式匹配和大小写修改:

string="abcdefgh123cbazyz"
echo ${string^^[a-d]}
输出:

ABCDefgh123CBAzyz

您可以使用Perl:

perl -lape 's/([a-d])/`uppercase $1`/eg' <<< "$string"

,但这将需要一个可执行的脚本命名为uppercase。Perl e (eval)标记在匹配时执行命令

另一种方式是sed:

function uppercase() { 
    echo ${1^^} 
}
export -f uppercase
string="abcdefgh123cbazyz"
echo "echo $(sed 's/([a-d])/$(uppercase 1)/g' <<< "$string")" | sh

使用tr:

echo abcdefgh123cbazyz | tr '[a-d]' '[A-D]'

sed:

echo abcdefgh123cbazyz | sed -r 's|[a-d]|U&|g'
输出:

ABCDefgh123CBAzyz

更新

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";
输出:

ABCDefgh123CBAzyz

在Perl中,您可以捕获组并将其传递给子例程,使用e标志:

perl -pe 'sub callback { return uc $_[0] } s/([a-d])/callback $1/eg' <<<"$string"

字符串的输出:

ABCDefgh123CBAzyz

这里我只是提供了我自己的包装器,围绕现有的函数uc,返回将字母转换为大写。您可以更改子例程的主体来做任何您想做的事情。

下面是您在GNU awk中如何做的(对于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

或使用任意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

最新更新