我写了一个Pascal函数来替换文件中的一整行,或者只是其中的一部分,以便在Inno Setup中使用:
function ReplaceInFile(const FilePath, OldLinePart, Replacement: String;
DoReplaceWholeLine, IsCaseSensitive: Boolean): Boolean;
var
FileLines: TArrayOfString;
Index: Integer;
FoundAtPos: Integer;
LeftOfOldLinePart: String;
RightOfOldLinePart: String;
IsReplaced: Boolean;
begin
Result := False;
if FileExists(FilePath) then begin
LoadStringsFromFile(FilePath, FileLines);
for Index := 0 to GetArrayLength(FileLines) - 1 do
begin
repeat
FoundAtPos := 0;
if IsCaseSensitive then
FoundAtPos := Pos(OldLinePart, FileLines[Index])
else
FoundAtPos := Pos(Uppercase(OldLinePart), Uppercase(FileLines[Index]));
if FoundAtPos > 0 then begin
if DoReplaceWholeLine then begin
FileLines[Index] := Replacement;
IsReplaced := True;
end
else begin
LeftOfOldLinePart := Copy(FileLines[Index], 1, FoundAtPos - 1);
RightOfOldLinePart := Copy(FileLines[Index], FoundAtPos
+ Length(OldLinePart), Length(FileLines[Index])
- Length(LeftOfOldLinePart + OldLinePart));
FileLines[Index] := LeftOfOldLinePart + Replacement + RightOfOldLinePart;
IsReplaced := True;
end;
end;
until FoundAtPos = 0;
end;
if IsReplaced then
if SaveStringsToFile(FilePath, FileLines, False) then
Result := True;
end;
end;
它曾经工作得很好,但只用替换了 FilePath 指定的文件的每一行上第一次出现的 OldLinePart。那是我添加重复循环的时候。逻辑是,当找不到更多匹配项时,Pos()
返回 0。然后它应该继续到下一行。然而,事实是,循环无限地运行,我不知道为什么。我尝试在 if FoundAtPos > 0
的 else
条款中添加一个 Break
语句,但没有运气......
编辑:显然已经很晚了。我正在用一个很长的字符串替换 OldLinePart......其中包含相同的单词。
此问题已按如下方式解决。
function ReplaceInFile(const FilePath, OldLinePart, Replacement: String; DoReplaceWholeLine, IsCaseSensitive: Boolean): Boolean;
var
FileLines: TArrayOfString;
Index: Integer;
SearchLinePart: String;
FoundAtPosition: Integer;
SearchOffset: Integer;
LeftOfOldLinePart: String;
RightOfOldLinePart: String;
IsReplaced: Boolean;
begin
Result := False;
if FileExists(FilePath) then
begin
LoadStringsFromFile(FilePath, FileLines);
for Index := 0 to GetArrayLength(FileLines) - 1 do
begin
SearchOffset := 0;
SearchLinePart := FileLines[Index];
repeat
FoundAtPosition := 0;
if IsCaseSensitive then
FoundAtPosition := SearchOffset + Pos(OldLinePart, SearchLinePart)
else
FoundAtPosition := SearchOffset + Pos(Uppercase(OldLinePart), Uppercase(SearchLinePart));
if FoundAtPosition > SearchOffset then
begin
if DoReplaceWholeLine then
begin
FileLines[Index] := Replacement;
IsReplaced := True;
Break;
end
else
begin
LeftOfOldLinePart := '';
RightOfOldLinePart := '';
LeftOfOldLinePart := Copy(FileLines[Index], 1, FoundAtPosition - 1);
RightOfOldLinePart := Copy(FileLines[Index], FoundAtPosition + Length(OldLinePart), Length(FileLines[Index]) - Length(LeftOfOldLinePart + OldLinePart));
FileLines[Index] := LeftOfOldLinePart + Replacement + RightOfOldLinePart;
IsReplaced := True;
SearchOffset := Length(LeftOfOldLinePart + Replacement);
SearchLinePart := RightOfOldLinePart;
end;
end;
until FoundAtPosition <= SearchOffset;
end;
if IsReplaced then
if SaveStringsToFile(FilePath, FileLines, False) then
Result := True;
end;
end;
我用对 StringRereplace 的单个调用替换了你的循环。这可以防止(无限)循环并解决问题。
请注意,您在IsReplaced
方面也有问题,例如 FileLines[4]
被替换,但不是FilesLine[last]
那么你的代码就不会调用SaveStringsToFile
。
它还在一定程度上简化了代码。
uses SysUtils;
function ReplaceInFile(const FilePath, OldLinePart, Replacement: String;
DoReplaceWholeLine, IsCaseSensitive: Boolean): Boolean;
var
FileLines: TArrayOfString;
Index: Integer;
TempStr: String;
IsReplaced: Boolean;
Flags: TReplaceFlags;
IsReplacedAnywhere: Boolean;
begin
Result := False;
if FileExists(FilePath) then begin
LoadStringsFromFile(FilePath, FileLines);
IsReplacedAnywhere:= false;
for Index := 0 to GetArrayLength(FileLines) - 1 do begin
if DoReplaceWholeLine then begin
IsReplaced :=
IsCaseSensitive and (Pos(OldLinePart, FileLines[Index]) > 0) or
not(IsCaseSensitive) and
(Pos(Uppercase(OldLinePart), Uppercase(FileLines[Index])) > 0);
if IsReplaced then FileLines[Index] := Replacement;
end
else begin
Flags:= [rfReplaceAll];
if not(IsCaseSensitive) then Flags:= Flags + [rfIgnoreCase];
TempStr:= StringReplace(FileLines[Index], OldLinePart, Replacement
,Flags);
IsReplaced := (TempStr <> FileLines[Index]);
if IsReplaced then FileLines[Index]:= TempStr;
end; {else}
IsReplacedAnywhere:= IsReplacedAnywhere or IsReplaced;
end; {for Index}
Result:= IsReplacedAnywhere
and SaveStringsToFile(FilePath, FileLines, False);
end; {if}
end;
让我知道这是否适合您。
现在应该使用 StringChangeEx 完成此操作。 很高兴它支持Unicode。 他通过删除旧函数来破坏旧脚本的方式并不好。 字符串替换不再编译;即使它是用于执行此操作的德尔菲函数。 StringChange 已被弃用。