我正在尝试获取一个例程,它会找到一个不遵循括号的字符串。例如,如果在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'?我还需要它来突出显示搜索字符串的整行。
答案 0 :(得分:3)
根据您发布的样本,您可以使用Delphi(XE和更高版本)正则表达式来匹配您指定的文本。在这里,我将您展示的三个示例行放入TMemo
(下面的代码中为Memo1
),评估正则表达式,并将找到的匹配项放入Memo2
- 只要您的TRichEdit
仅包含纯文本,您就可以使用相同的代码,将Memo1
和Memo2
分别替换为RichEdit1
和RichEdit2
。
我已更新两个片段中的代码,以显示如何获取确切位置(作为第一个字符的偏移量)和匹配结果的长度;您可以使用此功能使用SelStart
和SelLength
突出显示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;
这会产生以下结果:
如果您使用的是不包含正则表达式支持的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 - 我与生产它的公司没有关联,而只是该产品的用户。