5

我需要正则表达式帮助来创建一个 delphi 函数来替换 Rad Studio XE2 中的 HyperString ParseWord 函数。HyperString 是一个非常有用的字符串库,它从未跳转到 Unicode。我已经让它大部分工作了,但它根本不尊重引号分隔符。我需要它与下面描述的函数完全匹配:

函数 ParseWord(const Source,Table:String;var Index:Integer):String;

使用单字符分隔符表从左到右进行顺序标记解析。带引号的字符串中的分隔符将被忽略。表中不允许使用引号分隔符。

索引是一个指针(初始化为第一个单词的“1”),由函数更新以指向下一个单词。要检索下一个单词,只需使用先前返回的索引值再次调用该函数。

注意:如果 Length(Resultant) = 0,则没有可用的附加字。 带引号的字符串中的分隔符将被忽略。(我的重点)

这是我到目前为止所拥有的:

function ParseWord( const Source, Table: String; var Index: Integer):string;
var
  RE : TRegEx;
  match : TMatch;
  Table2,
  chars : string;
begin
  if index = length(Source) then
  begin
    result:= '';
    exit;
  end;

  // escape the special characters and wrap in a Group
  Table2 :='['+TRegEx.Escape(Table, false)+']';
  RE := TRegEx.create(Table2);
  match := RE.Match(Source,Index);
  if match.success then
  begin
    result := copy( Source, Index, match.Index - Index);
    Index := match.Index+match.Length;
  end
  else
  begin
    result := copy(Source, Index, length(Source)-Index+1);
    Index := length(Source);
  end;
end;

  while ( Length(result)= 0) and (Index<length(Source)) do
  begin
    Inc(Index);
    result := ParseWord(Source,Table, Index);
  end;

欢呼和感谢。

4

2 回答 2

1

我会尝试这个正则表达式Table2

Table2 := '''[^'']+''|"[^"]+"|[^' + TRegEx.Escape(Table, false) + ']+';

演示:
这个演示更像是一个 POC,因为我找不到在线的 delphi 正则表达式测试器。

  • 分隔符是space(ASCII code 32) 和pipe(ASCII code 124) 字符。
  • 测试语句是:

    toto titi "alloa toutou" 'dfg erre' 1245|coucou "nestor|delphi" "" ''

http://regexr.com?32i81

讨论:
我假设带引号的字符串是由两个单引号 ( ') 或两个双引号 ( ") 括起来的字符串。如果我错了,请纠正我。

正则表达式将匹配:

  • 单引号字符串
  • 双引号字符串
  • 不是由任何传递的分隔符组成的字符串

已知错误:
由于我不知道 ParseWord 如何处理字符串内的引号转义,因此正则表达式不支持此功能。

例如 :

  • 如何解释这个'foo''bar'?=> 两个令牌:'foo''bar'OR 一个令牌'foo''bar'
  • 这个案子呢:"foo""bar"?=> 两个令牌:"foo""bar"OR 一个令牌"foo""bar"
于 2012-10-23T09:26:39.513 回答
0

在我的原始代码中,我一直在寻找分隔符并将所有内容作为我的下一个匹配项,但是在寻找引号内的内容时,这个概念并没有延续。@Stephan 否定搜索的建议最终使我找到了可行的方法。我之前从未提到的另一个复杂情况是 HyperStr 可以使用任何东西作为引用字符。默认值为双引号,但您可以通过函数调用更改它。

在我的解决方案中,我已将 QuoteChar 明确硬编码为双引号,这适合我自己的目的,但将 Q​​uoteChar 设为全局并将其设置在另一个函数中将是微不足道的。我还用单引号(ascii 39)成功地测试了它,这在 Delphi 中是一个棘手的问题。

function ParseWord( const Source, Table: String; var Index: Integer):string;
var
  RE : TRegEx;
  match : TMatch;
  Table2: string;
  Source2 : string;
  QuoteChar : string;
begin
  if index = length(Source) then
  begin
    result:= '';
    exit;
  end;

  // escape the special characters and wrap in a Group
  QuoteChar := #39;
  Table2 :='[^'+TRegEx.Escape(Table, false)+QuoteChar+']*|'+QuoteChar+'.*?'+QuoteChar ;
  Source2 := copy(Source, Index, length(Source)-index+1);
  match := TRegEx.Match(Source2,Table2);
  if match.success then
  begin
    result := copy( Source2, match.index, match.length);
    Index := Index + match.Index + match.Length-1;
  end
  else
  begin
    result := copy(Source, Index, length(Source)-Index+1);
    Index := length(Source);
  end;
  while ( Length(result)= 0) and (Index<length(Source)) do
  begin
    Inc(Index);
    result := ParseWord(Source,Table, Index);
  end;

end;

该解决方案不会从带引号的字符串中去除引号字符,但我无法从我自己现有的代码中判断它是否应该,并且我无法使用 Hyperstr 进行测试。也许别人知道?

于 2012-10-26T17:22:57.617 回答