5

Rad StudioXE2のHyperStringParseWord関数を置き換えるdelphi関数を作成するには、正規表現のヘルプが必要です。HyperStringは、Unicodeにジャンプしたことのない非常に便利な文字列ライブラリでした。私はそれをほとんど機能させていますが、引用符の区切り文字をまったく尊重していません。以下に説明する関数と完全に一致する必要があります。

関数ParseWord(const Source、Table:String; var Index:Integer):String;

1文字の区切り文字のテーブルを使用した、左から右への順次トークン解析。引用符で囲まれた文字列内の区切り文字は無視されます。表では引用区切り文字は使用できません。

インデックスは、次の単語を指すように関数によって更新されるポインタ(最初の単語の場合は「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) + ']+';

デモ:
オンラインの Delphi 正規表現テスターが見つからなかったため、このデモは POC に近いものです。

  • 区切り文字はspace(ASCII コード32) とpipe(ASCII コード124) 文字です。
  • テスト文は次のとおりです。

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

http://regexr.com?32i81

ディスカッション:
引用符で囲まれた文字列は、2 つの単一引用符 ( ') または 2 つの二重引用符 ( ") で囲まれた文字列であると想定しています。私が間違っている場合は修正してください。

正規表現は次のいずれかに一致します。

  • 一重引用符で囲まれた文字列
  • 二重引用符で囲まれた文字列
  • 渡された区切り文字によって構成されていない文字列

既知のバグ:
ParseWord が文字列内の引用符エスケープを処理する方法を知らなかったため、正規表現はこの機能をサポートしていません。

例えば ​​:

  • これをどう解釈する'foo''bar'か?=> 2 つのトークン:'foo'および'bar'OR 1 つのトークン'foo''bar'
  • この場合もどうですか : "foo""bar"? => 2 つのトークン:"foo"および"bar"OR 1 つのトークン"foo""bar"
于 2012-10-23T09:26:39.513 に答える
0

元のコードでは、区切り文字を探して、それまでのすべてを次の一致として取り上げていましたが、引用符で囲まれたものを探すときに、その概念は引き継がれませんでした。@Stephanの検索を否定するという提案は、最終的にはうまくいくものに私を導きます。私が以前に言及したことのない追加の複雑さは、HyperStrが引用符文字として何でも使用できることです。デフォルトは二重引用符ですが、関数呼び出しで変更できます。

私のソリューションでは、QuoteCharを二重引用符として明示的にハードコーディングしました。これは私自身の目的に適していますが、QuoteCharをグローバルにして、別の関数内に設定するのは簡単です。また、一重引用符(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 に答える