我如何让Bash匹配正则表达式,而不是用常量字符串替换值,而是将匹配的值传递给函数,然后从函数的返回值中获取要替换的值。功能
类似于以下伪代码,它将[a-d]
的每个匹配替换为相同的字符,但大写:
function uppercase() { echo ${1^^}; }
string="abcdefgh123cbazyz"
echo ${string//[a-d]/uppercase()}
# output: ABCDef123CBAzyz
我并不特别,通常安装在Unix系统上的任何语言(例如sed
,awk
,甚至内置于bash
的有限正则表达式支持)可以使用。
答案 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