Delphi RichEdit查找包含字符串但不在括号后面的行

时间:2013-09-01 22:30:13

标签: delphi richedit

我正在尝试获取一个例程,它会找到一个不遵循括号的字符串。例如,如果在RichEdit中打开的文件包含这些CNC代码行,我希望它找到前两个并忽略第三个。在第二行中,它应该只找到并突出显示搜索字符串的第一次出现。此示例中的搜索字符串(mach.TOOL_CHANGE_CALL)为“T”。

N1T1M6
N1T1M6(1/4-20 TAP .5 DP.)
(1/4-20 TAP .5 DP.)

我已经走到这一步了,但我很难过。

procedure TMainForm.ToolButton3Click(Sender: TObject); // find tool number
var
  row:integer;
  sel_str:string;
  par:integer;
  tool:integer;
  tool_flag:integer ;
  line_counter:integer;
  tool_pos:integer;
  line_begin:integer;
  RE:TRichEdit;
begin
  RE:=(ActiveMDIChild as TMDIChild).RichEdit1;
  line_counter:=0;
  tool_flag:=0;
  tool_pos:=0;

  row:=SendMessage(RE.Handle,EM_LINEFROMCHAR,-1, RE.SelStart);

  while  tool_flag =0 do    
  begin
    RE.Perform(EM_LINESCROLL,0,line_counter);
    sel_str := RE.Lines[Line_counter];
    tool:=pos(mach.TOOL_CHANGE_CALL,sel_str);
    par:=pos('(',sel_str);
    if par=0 then 
      par:=pos('[',sel_str);
    tool_pos:=tool_pos+length(sel_str);

    if (tool>0) and (par = 0)  then
    begin
      RE.SetFocus;
      tool_pos:=tool_pos + line_counter-1;
      line_begin:=tool_pos-tool;
      RE.SelStart := line_begin;
      RE.SelLength := Length(sel_str);
      tool_flag:=1;
    end;
    inc (line_counter);
  end;
end;

我得到的结果是它会忽略第三个字符串,但也会忽略第二个字符串。它也不会在文件中找到后续出现的字符串,它只是从文本的开头开始,然后再次找到第一个字符串。我怎样才能找到第二个例子,然后在下一次点击按钮时找到下一个'T'?我还需要它来突出显示搜索字符串的整行。

1 个答案:

答案 0 :(得分:3)

根据您发布的样本,您可以使用Delphi(XE和更高版本)正则表达式来匹配您指定的文本。在这里,我将您展示的三个示例行放入TMemo(下面的代码中为Memo1),评估正则表达式,并将找到的匹配项放入Memo2 - 只要您的TRichEdit仅包含纯文本,您就可以使用相同的代码,将Memo1Memo2分别替换为RichEdit1RichEdit2

我已更新两个片段中的代码,以显示如何获取确切位置(作为第一个字符的偏移量)和匹配结果的长度;您可以使用此功能使用SelStartSelLength突出显示richedit中的匹配。

uses
  RegularExpressions;

procedure TForm1.Button1Click(Sender: TObject);
var
    Regex: TRegEx;
    MatchResult: TMatch;
begin
  Memo1.Lines.Clear;
  Memo1.Lines.Add('N1T1M6');
  Memo1.Lines.Add('N1T1M6(1/4-20 TAP .5 DP.)');
  Memo1.Lines.Add('(1/4-20 TAP .5 DP.)');
  Memo2.Clear;
  // See the text below for an explanation of the regular expression
  Regex := TRegEx.Create('^\w+T\w+', [roMultiLine]);
  MatchResult := Regex.Match(Memo1.Lines.Text);
  while MatchResult.Success do 
  begin
    Memo2.Lines.Add(MatchResult.Value +
                  ' Index: ' + IntToStr(MatchResult.Index) +
                  ' Length: ' + IntToStr(MatchResult.Length));
    MatchResult := MatchResult.NextMatch;
  end;
end;

这会产生以下结果:

Capture of results of above code

如果您使用的是不包含正则表达式支持的Delphi版本,则可以使用免费的TPerlRegEx进行一些次要的代码更改,以产生相同的结果:

uses
  PerlRegEx;

procedure TForm1.Button1Click(Sender: TObject);
var
  Regex: TPerlRegEx;
begin
  Memo1.Lines.Clear;
  Memo1.Lines.Add('N1T1M6');
  Memo1.Lines.Add('N1T1M6(1/4-20 TAP .5 DP.)');
  Memo1.Lines.Add('(1/4-20 TAP .5 DP.)');
  Memo2.Clear;
  Regex := TPerlRegEx.Create;
  try
    Regex.RegEx := '^\w+T\w+';
    Regex.Options := [preMultiLine];
    Regex.Subject := Memo1.Lines.Text;
    if Regex.Match then 
    begin
      repeat
        Memo2.Lines.Add(Regex.MatchedText +
                        ' Offset: ' + IntToStr(Regex.MatchedOffset) +
                        ' Length: ' + IntToStr(Regex.MatchedLength));
      until not Regex.MatchAgain;
    end;
  finally
    Regex.Free;
  end;
end;

上面的正则表达式(^\w+T\w+)表示:

Options: ^ and $ match at line breaks

Assert position at the beginning of a line (at beginning 
  of the string or after a line break character) «^»
Match a single character that is a “word character” (letters, 
  digits, and underscores) «\w+»
    Between one and unlimited times, as many times as possible, 
    giving back as needed (greedy) «+»
Match the character “T” literally «T»
Match a single character that is a “word character” (letters, 
  digits, and underscores) «\w+»
    Between one and unlimited times, as many times as possible, 
    giving back as needed (greedy) «+»

Created with RegexBuddy

你可以找到关于正则表达式here的体面教程。我用来计算正则表达式的工具(并且实际上为这两个例子生成了大部分Delphi代码)是RegexBuddy - 我与生产它的公司没有关联,而只是该产品的用户。