2015-06-14 136 views
2

我想写一个函数来提取两个标签之间的字符串。 问题是第一个标记在该字符串中是重复的,并且计数未知德尔福 - 提取标签之间的字符串(重复标签)

Str := 'Delphi App Hello Hello SomeText here Hello Hello Hello This is a Test!'; 

我要的究竟是提取你好这是一个测试!

  • TagF是最后你好
  • TAGL是测试!

TagF它的随机重复计数。

Function sExtractBetweenTagsB(Const s, LastTag, FirstTag: string): string; 
var 
    i, f : integer; 
    sTemp : string; 
begin 
    sTemp := s; 
    repeat 
    Delete(sTemp,Pos(FirstTag, sTemp),length(FirstTag)); 
    until AnsiPos(FirstTag,sTemp) = 0; 
    f := Pos(LastTag, sTemp); 
    Result:= FirstTag+' '+Copy(sTemp, 1, length(sTemp)); 
end; 

输出是:

Hello Delphi App SomeText here This is a Test! 
+1

尝试'LastDelimiter'功能 – MBo

+1

@Mbo:虽然方便,我宁愿用'PosEx'停留在32位,因为它具有同时'LastDelimiter一个Fastcode优化'没有。 – whosrdaddy

回答

2
Function sExtractBetweenTagsB(Const s, LastTag, FirstTag: string): string; 
var 
    pLast,pFirst,pNextFirst : Integer; 
begin 
    pFirst := Pos(FirstTag,s); 
    pLast := Pos(LastTag,s); 
    while (pLast > 0) and (pFirst > 0) do begin 
    if (pFirst > pLast) then // Find next LastTag 
     pLast := PosEx(LastTag,s,pLast+Length(LastTag)) 
    else 
    begin 
     pNextFirst := PosEx(FirstTag,s,pFirst+Length(FirstTag)); 
     if (pNextFirst = 0) or (pNextFirst > pLast) then begin 
     Result := Copy(s,pFirst,pLast-pFirst+Length(LastTag)); 
     Exit; 
     end 
     else 
     pFirst := pNextFirst; 
    end; 
    end; 
    Result := ''; 
end; 

var 
    s: String; 

begin 
    s := 'Delphi App Hello Hello SomeText here Hello Hello Hello This is a Test! Hello'; 
    WriteLn(sExtractBetweenTagsB(s,'Test','Hello')); 
end. 

输出:

Hello This is a Test 
+0

只是其辉煌 – RepeatUntil

4

可以使用PosEx功能来扫描您的字符串标记,然后向前搜索:

Input: "Delphi App Hello Hello SomeText here Hello Hello Hello This is a Test!" 
Ouput: "Hello This is a Test!" 
Input: " Test! Delphi App Hello Hello SomeText here Hello Hello Hello This is a Test! Some end chars" 
Ouput: "Hello This is a Test!" 

program SO30827180; 

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    SysUtils, 
    StrUtils; 

function ExtractString(const Input : String; const TagF: String; const TagL : String) : String; 

var 
    LastPos : Integer; 
    NewPos : Integer; 

begin 
Result := ''; 
NewPos := Pos(TagF, Input); 
if NewPos <> 0 then 
    begin 
    LastPos := NewPos; 
    // scan to last start tag 
    while true do 
    begin 
    NewPos := PosEx(TagF, Input, NewPos+1); 
    if NewPos <> 0 then 
     LastPos := NewPos 
    else 
     Break; 
    end; 
    // now seek end tag, starting from last starting tag position 
    NewPos := PosEx(TagL, Input, LastPos+1); 
    if NewPos <> 0 then 
    Result := Copy(Input, LastPos, NewPos-LastPos+Length(TagL)); 
    end; 
end; 

var 
    Line : String; 

begin 
Line := 'Delphi App Hello Hello SomeText here Hello Hello Hello This is a Test!'; 
Writeln(Format('Input: "%s"', [Line])); 
Writeln(Format('Ouput: "%s"', [ExtractString(Line, 'Hello', 'Test!')])); 
Line := ' Test! Delphi App Hello Hello SomeText here Hello Hello Hello This is a Test! Some end chars'; 
Writeln(Format('Input: "%s"', [Line])); 
Writeln(Format('Ouput: "%s"', [ExtractString(Line, 'Hello', 'Test!')])); 
Readln; 
end. 

从示例输出

+0

如果最后一个标签后面有第一个标签,则不起作用。 –

+2

@LURD那么需求并不那么清楚,是吗?如果我正确理解OP,提取将从最后一个开始标记处开始。如果之后没有结束标签,那么结果应该是空的,而不是? – whosrdaddy

+1

@whosrdaddy这就是我要求的感谢。 – RepeatUntil

2

要做到这一点,最简单的方法是使用正则表达式:?!

program Project1; 

{$APPTYPE CONSOLE} 

uses 
    RegularExpressions; 

var 
    regEx : TRegEx; 
    testString : string; 
    m : TMatch; 
begin 
    testString := 'Delphi App Hello Hello SomeText here Hello Hello Hello This is a Test!'; 

    regEx := TRegEx.Create('(Hello(?!.*Hello).*?Test!)'); 
    m := regEx.Match(testString); 

    if m.Success then 
    WriteLn(m.Value) 
    else 
    WriteLn('No match.'); 
    ReadLn; 
end. 

这里正则表达式是

  • (你好(*你好)
    - 匹配“Hello”和str中后面没有“Hello”的实例ing(贪婪lookahead)
  • 。*?
    - 懒匹配任何
  • 测试)
    ! - 匹配 “测试!”

如果要概括:

function ExtractBetweenTags(const s : string; FirstTag, LastTag : string) : string; 
var 
    regEx : TRegEx; 
begin 
    regEx := TRegEx.Create(Format('(%s(?!.*%s).*?%s)', [FirstTag, FirstTag, LastTag])); 
    result := regEx.Match(s).Value; 
end; 
相关问题