将两个其他字符串之间的所有字符串实例写入日志文件
Writing all instances of strings between two other strings to logfile
在查看了 Delphi extract string between to 2 tags 并尝试了 Andreas Rejbrand 给出的代码后,我意识到我需要一个不会在一个标签后停止的版本——我的目标是写下两个标签之间出现的所有值几个 .xml 文件中的字符串到日志文件。
<screen> xyz </screen> blah blah <screen> abc </screen>
-> 使用
提供日志文件
xyz
美国广播公司
...等等。
我尝试的是删除函数读取的一部分文本,这样当函数重复时,它会转到所需字符串的下一个实例,然后将其也写入日志文件,直到有没有剩余匹配项 - 布尔函数将为真并且函数可以停止 - 根据 link.
中的版本略微修改的函数下方
function ExtractText(const Tag, Text: string): string;
var
StartPos1, StartPos2, EndPos: integer;
i: Integer;
mytext : string;
bFinished : bool;
begin
bFinished := false;
mytext := text;
result := '';
while not bFinished do
begin
StartPos1 := Pos('<' + Tag, mytext);
if StartPos1 = 0 then bFinished := true;
EndPos := Pos('</' + Tag + '>', mytext);
StartPos2 := 0;
for i := StartPos1 + length(Tag) + 1 to EndPos do
if mytext[i] = '>' then
begin
StartPos2 := i + 1;
break;
end;
if (StartPos2 > 0) and (EndPos > StartPos2) then
begin
result := result + Copy(mytext, StartPos2, EndPos - StartPos2);
delete (mytext, StartPos1, 1);
end
所以我创建了表单并分配了一个日志文件。
procedure TTagtextextract0r.FormCreate(Sender: TObject);
begin
Edit2.Text:=(TDirectory.GetCurrentDirectory);
AssignFile(LogFile, 'Wordlist.txt');
ReWrite(LogFile);
CloseFile(Logfile);
end;
为了获取相关文件,我单击一个按钮,然后读取它们。
procedure TTagtextextract0r.Button3Click(Sender: TObject);
begin
try
sD := TDirectory.GetCurrentDirectory;
Files:= TDirectory.GetFiles(sD, '*.xml');
except
exit
end;
j:=Length(Files);
for k := 0 to j-1 do
begin
Listbox2.Items.Add(Files[k]);
sA:= TFile.ReadAllText(Files[k]);
iL:= Length(sA);
AssignFile(LogFile, 'Wordlist.txt');
Append(LogFile);
WriteLn(LogFile, (ExtractText('screen', sA)));
CloseFile (LogFile);
end;
end;
end.
我的问题是,如果函数中没有布尔循环,应用程序只会为每个文件写入一行,然后停止,但是使用布尔代码,应用程序会陷入无限循环 - 但我不太明白循环没有结束的地方。是不是 "WriteLn" 命令不能输出函数的结果?如果不能,我不知道如何为函数的每个 运行 换行 - 我在这里做错了什么?
首先你需要掌握调试
查看 了解如何暂停和调试异常程序的简介。
另请阅读 Setting and modifying breakpoints 以了解如何使用断点。如果您单步执行代码,您很快就会发现哪里出错了。
然后是你的问题:
在旧的 Delphi 版本中(直到 Delphi XE2),您可以使用 PosEx()
函数(如评论中所建议的),这将简化 [=13= 中的代码] 功能显着。从 Delphi XE3 开始,System.Pos()
函数已扩展为具有与 PosEx()
相同的功能,即第三个参数 Offset: integer
由于您位于 Delphi 10 Seattle,因此您可以交替使用 System.StrUtils.PosEx()
或 System.Pos()
。
System.StrUtils.PosEx
PosEx() returns the index of SubStr in S, beginning the search at
Offset
function PosEx(const SubStr, S: string; Offset: Integer = 1): Integer; inline; overload;
ExtractText()
的实现可能如下所示(PosEx()
):
function ExtractText(const tag, text: string): string;
var
startPos, endPos: integer;
begin
result := '';
startPos := 1;
repeat
startPos := PosEx('<'+tag, text, startpos);
if startPos = 0 then exit;
startPos := PosEx('>', text, startPos)+1;
if startPos = 1 then exit;
endPos := PosEx('</'+tag+'>', text, startPos);
if endPos = 0 then exit;
result := result + Copy(text, startPos, endPos - startPos) + sLineBreak;
until false;
end;
我在每个找到的文本后添加了 sLineBreak
(在单元 System.Types
中),否则它应该按您的预期工作(我相信)。
在查看了 Delphi extract string between to 2 tags 并尝试了 Andreas Rejbrand 给出的代码后,我意识到我需要一个不会在一个标签后停止的版本——我的目标是写下两个标签之间出现的所有值几个 .xml 文件中的字符串到日志文件。
<screen> xyz </screen> blah blah <screen> abc </screen>
-> 使用
提供日志文件
xyz
美国广播公司
...等等。
我尝试的是删除函数读取的一部分文本,这样当函数重复时,它会转到所需字符串的下一个实例,然后将其也写入日志文件,直到有没有剩余匹配项 - 布尔函数将为真并且函数可以停止 - 根据 link.
中的版本略微修改的函数下方function ExtractText(const Tag, Text: string): string;
var
StartPos1, StartPos2, EndPos: integer;
i: Integer;
mytext : string;
bFinished : bool;
begin
bFinished := false;
mytext := text;
result := '';
while not bFinished do
begin
StartPos1 := Pos('<' + Tag, mytext);
if StartPos1 = 0 then bFinished := true;
EndPos := Pos('</' + Tag + '>', mytext);
StartPos2 := 0;
for i := StartPos1 + length(Tag) + 1 to EndPos do
if mytext[i] = '>' then
begin
StartPos2 := i + 1;
break;
end;
if (StartPos2 > 0) and (EndPos > StartPos2) then
begin
result := result + Copy(mytext, StartPos2, EndPos - StartPos2);
delete (mytext, StartPos1, 1);
end
所以我创建了表单并分配了一个日志文件。
procedure TTagtextextract0r.FormCreate(Sender: TObject);
begin
Edit2.Text:=(TDirectory.GetCurrentDirectory);
AssignFile(LogFile, 'Wordlist.txt');
ReWrite(LogFile);
CloseFile(Logfile);
end;
为了获取相关文件,我单击一个按钮,然后读取它们。
procedure TTagtextextract0r.Button3Click(Sender: TObject);
begin
try
sD := TDirectory.GetCurrentDirectory;
Files:= TDirectory.GetFiles(sD, '*.xml');
except
exit
end;
j:=Length(Files);
for k := 0 to j-1 do
begin
Listbox2.Items.Add(Files[k]);
sA:= TFile.ReadAllText(Files[k]);
iL:= Length(sA);
AssignFile(LogFile, 'Wordlist.txt');
Append(LogFile);
WriteLn(LogFile, (ExtractText('screen', sA)));
CloseFile (LogFile);
end;
end;
end.
我的问题是,如果函数中没有布尔循环,应用程序只会为每个文件写入一行,然后停止,但是使用布尔代码,应用程序会陷入无限循环 - 但我不太明白循环没有结束的地方。是不是 "WriteLn" 命令不能输出函数的结果?如果不能,我不知道如何为函数的每个 运行 换行 - 我在这里做错了什么?
首先你需要掌握调试
查看
另请阅读 Setting and modifying breakpoints 以了解如何使用断点。如果您单步执行代码,您很快就会发现哪里出错了。
然后是你的问题:
在旧的 Delphi 版本中(直到 Delphi XE2),您可以使用 PosEx()
函数(如评论中所建议的),这将简化 [=13= 中的代码] 功能显着。从 Delphi XE3 开始,System.Pos()
函数已扩展为具有与 PosEx()
相同的功能,即第三个参数 Offset: integer
由于您位于 Delphi 10 Seattle,因此您可以交替使用 System.StrUtils.PosEx()
或 System.Pos()
。
System.StrUtils.PosEx
PosEx() returns the index of SubStr in S, beginning the search at Offset
function PosEx(const SubStr, S: string; Offset: Integer = 1): Integer; inline; overload;
ExtractText()
的实现可能如下所示(PosEx()
):
function ExtractText(const tag, text: string): string;
var
startPos, endPos: integer;
begin
result := '';
startPos := 1;
repeat
startPos := PosEx('<'+tag, text, startpos);
if startPos = 0 then exit;
startPos := PosEx('>', text, startPos)+1;
if startPos = 1 then exit;
endPos := PosEx('</'+tag+'>', text, startPos);
if endPos = 0 then exit;
result := result + Copy(text, startPos, endPos - startPos) + sLineBreak;
until false;
end;
我在每个找到的文本后添加了 sLineBreak
(在单元 System.Types
中),否则它应该按您的预期工作(我相信)。