1

我正在尝试获得一个可以找到不跟随括号的字符串的例程。例如,如果在 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”?我还需要它来突出显示搜索字符串所在的整行。

4

1 回答 1

3

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

我已经更新了两个片段中的代码,以显示如何获取匹配结果的确切位置(作为第一个字符的偏移量)和长度;您可以使用它在 Richedit 中使用SelStart和突出显示匹配项SelLength

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;

这会产生以下结果:

捕获上述代码的结果

如果您使用的 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+) 表示:

选项: ^ 和 $ 匹配换行符

在行首断言位置(在开头
  字符串或换行符之后)«^»
匹配作为“单词字符”的单个字符(字母、
  数字和下划线)«\w+»
    在一次和无限次之间,尽可能多次,
    根据需要回馈(贪婪)«+»
匹配字符“T”字面意思«T»
匹配作为“单词字符”的单个字符(字母、
  数字和下划线)«\w+»
    在一次和无限次之间,尽可能多次,
    根据需要回馈(贪婪)«+»

使用 RegexBuddy 创建

你可以在这里找到一个关于正则表达式的不错的教程。我用于计算正则表达式(实际上为这两个示例生成大部分 Delphi 代码)的工具是RegexBuddy——我不隶属于生产它的公司,而只是该产品的用户。

于 2013-09-02T01:19:54.140 回答