使用自定义处理替换另一个字符串中出现的字符串
Replace occurrences of a string in another string with custom processing
假设我有一个字符串
myString := 'aa12bb23cc34dd'
我想用它的值乘以 2 来替换每个出现的数字(我的实际应用会更复杂,这是为了示例):
myUpdatedString := 'aa24bb46cc68dd'
我知道 Regexpr 中的 ReplaceRegExpr 可以像 Sed 一样使用,但它不会将函数作为参数应用于匹配的元素。
目前,我正在做这样的事情(可能有点 ugly/invalid 但重要的是做事的方式):
program Project1;
uses
SysUtils, RegExpr;
// The function I would like to call on my matched element
function foo(const x: integer): integer;
begin
result = x * 2;
end;
function bar(const base, s: string): string;
var
pos: integer;
s2: string;
begin
// Application of foo
s2 := foo(StrToInt(s)).ToString;
// Substitution of the matched string
result = StringReplace(base, s, s2);
end;
var
re: TRegExpr;
myString, myUpdatedString: string;
begin
myString := 'aa12bb23cc34dd';
re := TRegExpr.Create('[0-9]+');
if re.Exec(myString) then
begin
// For each matched elements
myUpdatedString := bar(myString , re.Match[1]);
while re.ExecNext do
begin
myUpdatedString := bar(myString , re.Match[1]);
end;
end;
re.Free;
end.
有没有更轻松或更优雅的方法?
像 ReplaceRegExpr 这样将函数作为参数应用于匹配元素的函数是最好的,但我找不到。
感谢您的帮助!
编辑:在我的实际应用中,我不需要替换数字,而是替换 HTML 流的各种标签中的属性值。我想修改各种标签中的各种元素,这些值需要大量计算才能知道用什么替换它们。我认为这是一个简单问题的大量信息。
TRegExpr
已经带有 .Replace()
和 .ReplaceEx()
,您可以将 TRegExprWReplaceFunction
形式的函数交给它们,每个匹配事件都会调用该函数。您决定结果,然后将其用作比赛的替代品。这样你就可以自定义它了。示例:
type
TDum= class // Must be a function of object, hence a helper class
class function MyReplace( re: TRegExpr ): String;
end;
class function TDum.MyReplace( re: TRegExpr ): String;
begin
// Example: convert matching text to number, double it, convert back to text
result:= IntToStr( StrToInt( re.Match[1] )* 2 );
end;
...
myUpdatedString:= re.Replace( 'aa12bb23cc34dd', TDum.MyReplace );
// Should have become 'aa24bb46cc68dd'
如果您查看 TRegExp 的源代码,您会发现这些方法与您已经使用 .Exec()
和 .ExecNext()
构建的方法非常相似。
假设我有一个字符串
myString := 'aa12bb23cc34dd'
我想用它的值乘以 2 来替换每个出现的数字(我的实际应用会更复杂,这是为了示例):
myUpdatedString := 'aa24bb46cc68dd'
我知道 Regexpr 中的 ReplaceRegExpr 可以像 Sed 一样使用,但它不会将函数作为参数应用于匹配的元素。
目前,我正在做这样的事情(可能有点 ugly/invalid 但重要的是做事的方式):
program Project1;
uses
SysUtils, RegExpr;
// The function I would like to call on my matched element
function foo(const x: integer): integer;
begin
result = x * 2;
end;
function bar(const base, s: string): string;
var
pos: integer;
s2: string;
begin
// Application of foo
s2 := foo(StrToInt(s)).ToString;
// Substitution of the matched string
result = StringReplace(base, s, s2);
end;
var
re: TRegExpr;
myString, myUpdatedString: string;
begin
myString := 'aa12bb23cc34dd';
re := TRegExpr.Create('[0-9]+');
if re.Exec(myString) then
begin
// For each matched elements
myUpdatedString := bar(myString , re.Match[1]);
while re.ExecNext do
begin
myUpdatedString := bar(myString , re.Match[1]);
end;
end;
re.Free;
end.
有没有更轻松或更优雅的方法?
像 ReplaceRegExpr 这样将函数作为参数应用于匹配元素的函数是最好的,但我找不到。
感谢您的帮助!
编辑:在我的实际应用中,我不需要替换数字,而是替换 HTML 流的各种标签中的属性值。我想修改各种标签中的各种元素,这些值需要大量计算才能知道用什么替换它们。我认为这是一个简单问题的大量信息。
TRegExpr
已经带有 .Replace()
和 .ReplaceEx()
,您可以将 TRegExprWReplaceFunction
形式的函数交给它们,每个匹配事件都会调用该函数。您决定结果,然后将其用作比赛的替代品。这样你就可以自定义它了。示例:
type
TDum= class // Must be a function of object, hence a helper class
class function MyReplace( re: TRegExpr ): String;
end;
class function TDum.MyReplace( re: TRegExpr ): String;
begin
// Example: convert matching text to number, double it, convert back to text
result:= IntToStr( StrToInt( re.Match[1] )* 2 );
end;
...
myUpdatedString:= re.Replace( 'aa12bb23cc34dd', TDum.MyReplace );
// Should have become 'aa24bb46cc68dd'
如果您查看 TRegExp 的源代码,您会发现这些方法与您已经使用 .Exec()
和 .ExecNext()
构建的方法非常相似。