Delphi中通配符字符串搜索及字面量*、?匹配的实现方案咨询
解决方案:匹配字面量通配符的两种实现方式
一、基于正则表达式自行实现
TMask默认将*和?解析为通配符,要匹配它们的字面量,核心是先对搜索模式中的特殊字符做转义处理,再通过正则完成匹配。
实现思路
- 先转义正则语法中的特殊字符(包括
*、?),避免被正则引擎当作元字符解析; - 如果需要保留原有通配符功能(区分字面量和通配符),可约定转义符(比如
\):用户输入\*表示字面量*,输入*仍作为通配符; - 使用Delphi自带的
RegularExpressions单元完成最终匹配。
示例代码
uses RegularExpressions; function MatchWithLiteralWildcards(const SearchPattern, Content: string): Boolean; var RegexPattern: string; begin // 转义所有正则特殊字符 RegexPattern := TRegEx.Escape(SearchPattern); // 若需区分通配符与字面量,先处理转义规则:把\*转为字面量*,\?转为字面量? // RegexPattern := StringReplace(RegexPattern, '\\\*', '\*', [rfReplaceAll]); // RegexPattern := StringReplace(RegexPattern, '\\\?', '\?', [rfReplaceAll]); // 将原本的通配符转换为正则语法 RegexPattern := StringReplace(RegexPattern, '\*', '.*', [rfReplaceAll]); RegexPattern := StringReplace(RegexPattern, '\?', '.', [rfReplaceAll]); // 匹配整个字符串 Result := TRegEx.IsMatch(Content, '^' + RegexPattern + '$'); end; // 使用示例: // 匹配字面量*** → MatchWithLiteralWildcards('***', Content) // 匹配通配符*加字面量? → 启用注释转义后,调用MatchWithLiteralWildcards('*\?', Content)
二、轻量替代:自定义简易通配符解析
如果不想引入正则或第三方库,可以自己实现一个支持转义的通配符匹配函数,手动区分字面量和通配符。
示例代码
function SimpleWildcardMatch(const Pattern, Content: string; EscapeChar: Char = '\'): Boolean; var PIdx, CIdx: Integer; PLen, CLen: Integer; begin PIdx := 1; CIdx := 1; PLen := Length(Pattern); CLen := Length(Content); Result := False; while (PIdx <= PLen) and (CIdx <= CLen) do begin if Pattern[PIdx] = EscapeChar then begin // 转义字符后接的内容作为字面量匹配 Inc(PIdx); if PIdx > PLen then Break; if Pattern[PIdx] <> Content[CIdx] then Exit; Inc(PIdx); Inc(CIdx); end else if Pattern[PIdx] = '*' then begin // 通配符*:匹配任意长度字符 Inc(PIdx); if PIdx > PLen then begin Result := True; Exit; end; // 递归匹配剩余模式 while CIdx <= CLen do begin if SimpleWildcardMatch(Copy(Pattern, PIdx, PLen - PIdx + 1), Copy(Content, CIdx, CLen - CIdx + 1), EscapeChar) then begin Result := True; Exit; end; Inc(CIdx); end; end else if Pattern[PIdx] = '?' then begin // 通配符?:匹配单个任意字符 Inc(PIdx); Inc(CIdx); end else begin // 普通字符:精确匹配 if Pattern[PIdx] <> Content[CIdx] then Exit; Inc(PIdx); Inc(CIdx); end; end; // 校验是否完全匹配到末尾 Result := (PIdx > PLen) and (CIdx > CLen); end; // 使用示例: // 匹配字面量*** → SimpleWildcardMatch('\*\*\*', Content) // 匹配以abc开头、以?结尾的内容 → SimpleWildcardMatch('abc*\?', Content)
内容的提问来源于stack exchange,提问作者MyICQ
相关产品推荐
相关产品推荐

