将两个其他字符串之间的所有字符串实例写入日志文件

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 中),否则它应该按您的预期工作(我相信)。