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

时间:2014-08-11 10:45:54

标签: regex bash awk sed

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

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

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

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

5 个答案:

答案 0 :(得分:4)

Bash无法在parameter expansion内使用用户定义的函数。

要完成您想要的操作,请使用pattern matching进行大小写修改:

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

输出:

ABCDefgh123CBAzyz

答案 1 :(得分:1)

您可以使用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

答案 2 :(得分:0)

使用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 }

使用Python的Callbak:

import re

s = "abcdefgh123cbazyz"

def repl(m):
    return m.upper()

print(re.sub('\[\[:(.+?):\]\]', repl, s))

使用Perl回调:

my $s = "abcdefgh123cbazyz";
$s =~ s/([a-d])/uc($1)/eg;
print "${s}\n";

输出:

ABCDefgh123CBAzyz

答案 3 :(得分:0)

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

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

字符串的输出:

ABCDefgh123CBAzyz

这里我刚刚提供了我自己的包装器,它围绕现有的函数uc,它将字母转换为大写。您可以更改子例程的主体以执行任何操作。

答案 4 :(得分:0)

FWIW这里是你如何在GNU awk中做到的(对于第4个arg 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

或与任何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