随笔 - 2146  文章 - 97 评论 - 11767 trackbacks - 253


假如有这样一串文本: AAA1 BBB2 AA11 BB22 A111 B222 AAAA

可以用表达式: [A-Za-z]+\d+ 提取到前六个字串. 测试代码:
uses RegularExpressions;

procedure TForm1.FormCreate(Sender: TObject);
var
  Regex: IRegex; { RegularExpressions 提倡使用 IRegex 而不是 TRegex}
  Match: IMatch; { IMatch 表示匹配到的若干个字串中的一个 }
begin
  { 构建表达式 }
  Regex := TRegex.Create('[A-Za-z]+\d+');

  { 下面就匹配出符合表达式的第一个字串 }
  Match := Regex.Match('AAA1 BBB2 AA11 BB22 A111 B222 AAAA');
  { 可用 Match.Value 获取匹配到的文本; 这里会是: AAA1 }
  { 可用 Match.Length 获取文本的长度; 这里会是: 4 }
  { 可用 Match.Index 获取字串在原串中的位置; 这里会是: 1, 第二个会是 6 }

  { 下面程序将遍历出所有匹配到的子串 }
  while Match.Success do       { IMatch.Success: 是否成功匹配 }
  begin
    ShowMessage(Match.Value);
    Match := Match.NextMatch;  { IMatch.NextMatch: 继续匹配下一个, 并返回下一个 IMatch 对象 }
  end;
end;


还是面对前面的文本: AAA1 BBB2 AA11 BB22 A111 B222 AAAA

假如在之前匹配的基础上, 同时想提取其中的 "字母" 或 "数字", 就要用到子表达式;

譬如, 表达式可以这样写: ([A-Za-z]+)(\d+)

匹配到的子表达式会放置在 IMatch.Groups 中;
Groups 是一个 IGroup 对象的集合, 它的元素总数 = 子表达式个数 + 1; 示例:
uses RegularExpressions;

procedure TForm1.FormCreate(Sender: TObject);
var
  Regex: IRegex;
  Match: IMatch;
  s,w,n: string;
begin
  Regex := TRegex.Create('([A-Za-z]+)(\d+)');
  Match := Regex.Match('AAA1 BBB2 AA11 BB22 A111 B222 AAAA');

  while Match.Success do
  begin
    s := Match.Groups[0].Value; { Groups[0] 放置整个表达式的匹配结果 }
    w := Match.Groups[1].Value; { Groups[1] 放置第一个子表达式的匹配结果 }
    n := Match.Groups[2].Value; { Groups[2] 放置第二个子表达式的匹配结果 }
    ShowMessageFmt('子串: %s; 字母: %s; 数字: %s', [s, w, n]);
    Match := Match.NextMatch;
  end;
(*
子串: AAA1; 字母: AAA; 数字: 1
子串: BBB2; 字母: BBB; 数字: 2
子串: AA11; 字母: AA; 数字: 11
子串: BB22; 字母: BB; 数字: 22
子串: A111; 字母: A; 数字: 111
子串: B222; 字母: B; 数字: 222
*)
end;


通过正则表达式主要就做两个工作: 查找、替换; 上面就是查找的基本思路, 再看替换, 直接是例子:
uses RegularExpressions;

procedure TForm1.FormCreate(Sender: TObject);
var
  Regex: IRegex;
  str: string;
begin
  Regex := TRegex.Create('([A-Za-z]+)(\d+)');

  { 把表达式匹配到的文本替换为 ◆ }
  str := Regex.Replace('AAA1 BBB2 AA11 BB22 A111 B222 AAAA', '◆');
  ShowMessage(str); { ◆ ◆ ◆ ◆ ◆ ◆ AAAA }

  { 把表达式匹配到的文本替换为 "第一个子表达式的匹配结果" }
  str := Regex.Replace('AAA1 BBB2 AA11 BB22 A111 B222 AAAA', '$1');
  ShowMessage(str); { AAA BBB AA BB A B AAAA }

  { 把表达式匹配到的文本替换为 "第二个子表达式的匹配结果", 这里相当于删除数字 }
  str := Regex.Replace('AAA1 BBB2 AA11 BB22 A111 B222 AAAA', '$2');
  ShowMessage(str); { 1 2 11 22 111 222 AAAA }
end;


在替换中使用 $1 $2, 下面是所有类似引用的列表:
$n      // 第几个子表达式, $0 表示整个表达式
$&      // 同 $0
$+      // 最后一个子表达式; 在上面例子中相当于 $2

$_      // 替换整个输入字符串
$`      // 替换匹配前的输入字符串的所有文本
$'      // 替换匹配后的输入字符串的所有文本; 这在 Delphi 中得写作: $''

$$      // 既然用 $ 做转义, 如果需要这个符号本身, 可以 $$

$<name> // 指定名称的子子表达式; 当前版本不支持


上面这些不是全部, 但已是主要脉络; 其他内容也都是围绕这个思路.

posted on 2010-01-07 10:08  万一  阅读(...)  评论(...编辑  收藏