2016-10-22 1 views
1

Ich muss eine Teilzeichenfolge nach einem bestimmten Trennzeichen extrahieren, aber wenn das angegebene Trennzeichen zwischen zwei anderen Tags ist, sollte es ignoriert werden.Wie extrahiere ich Sub-String nach dem Delimiter aber ignoriere ich, wenn zwischen zwei Tags gefunden?

Nehmen wir zum Beispiel diesen Test string:

Die schnelle < "@brown Fuchs"> springt über den faulen Hund. Die schnelle @braune Fuchs über den faulen Hund springt

Die gewünschte Ausgabe wäre:

braune Fuchs springt über den faulen Hund

Dies liegt daran, die first found @ delimiter liegt zwischen zwei "" und sollte daher ignoriert werden, das zweite @ delimiter ist nicht innerhalb "" und so sollte der Text danach extrahiert werden.

Ich bin in der Lage, die Ausgangsposition des @ Trennzeichen zu finden, indem Pos und Extrahieren der Text rechts davon wie unten gezeigt:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    S: string; 
    I: Integer; 
begin 
    S := 'The quick <"@brown fox"> jumps over the lazy dog. The quick @brown fox jumps over the lazy dog'; 
    I := Pos('@', S); 
    if I > 0 then 
    begin 
    ShowMessage(Copy(S, I, Length(S))); 
    end; 
end; 

dies jedoch immer die erste @ Begrenzer finden unabhängig davon, ob es ist von zwei "" umgeben oder nicht. Das Ergebnis aus der oben ist:

@brown Fuchs "> springt über den faulen Hund Die schnelle @braune Fuchs über springt die faulen Hund

wo das gewünschte Ergebnis sein sollte.:

braune Fuchs springt über den faulen Hund

Wie kann ich den Code ändern, um @ Trennzeichen zu ignorieren, wenn Pos verwendet wird, wenn das Trennzeichen zwischen zwei "" -Tags liegt? Ich möchte nur das erste @ Trennzeichen finden und den Text anschließend kopieren.

Es spielt auch keine Rolle, ob es irgendwelche anderen @ Trennzeichen nach dem ersten gültigen eine gefunden wird, zum Beispiel diese auch gültig sein sollte:

Die schnelle < „@brown Fuchs“> springt über die fauler Hund. Die schnelle @braune Fuchs @ springt ov @ er die faulen @ Hund

Sollte Rückkehr noch:

braune Fuchs springt über den faulen Hund

Weil wir sind nur an dem ersten gültigen @ Trennzeichen interessiert, ignorieren alles andere danach und ignorieren alles zwischen zwei "" -Tags.

Bitte beachten obwohl ich getaggt Delphi ich Lazarus in erster Linie verwenden so ideal wäre ich brauche Hilfe mit einer Lösung kommen, die keine Magie Hilfe mit String Helfer usw.

Dank nicht verwendet.

Antwort

1

Um herauszufinden, ob die @ nicht innerhalb " umschließenden Tags ist, die Zeichenfolge von Anfang an analysieren.

Wenn nach einem öffnenden Tag ein Trennzeichen gefunden wird, aber kein schließendes Tag, extrahiert diese Routine auch das Ergebnis.

function ExtractString(const s: String): String; 
var 
    tagOpen: Boolean; 
    delimiterPos,i,j: Integer; 
begin 
    tagOpen := false; 
    delimiterPos := 0; 
    Result := ''; 
    for i := 1 to Length(s) do begin 
    if (s[i] = '"') then begin 
     tagOpen := not tagOpen; 
     delimiterPos := 0; 
    end 
    else begin 
     if (s[i] = '@') then begin 
     if (delimiterPos = 0) then 
      delimiterPos := i; 
     if not tagOpen then // Found answer 
      Break; 
     end; 
    end;   
    end; 

    // If there is no closing tag and a delimiter is found 
    // since the last opening tag, deliver a result. 
    if (delimiterPos > 0) then begin 
    // Finally extract the string and remove all `@` delimiters. 
    SetLength(Result,Length(s)-delimiterPos); 
    j := 0; 
    for i := 1 to Length(Result) do begin 
     Inc(delimiterPos); 
     if (s[delimiterPos] <> '@') then begin 
     Inc(j); 
     Result[j] := s[delimiterPos]; 
     end; 
    end; 
    SetLength(Result,j);  
    end; 
end; 
+0

brillant, und vielen Dank für auch in den Kommentaren hinzugefügt :) – Craig

0
procedure TForm1.Button1Click(Sender: TObject); 
var 
    S: string; 
    L, I: Integer; 
    take : Boolean; 
begin 
    S := 'The quick <"@brown fox"> jumps over the lazy dog. The quick @brown fox jumps over the lazy dog'; 
    L := Length(S); 
    I := Pos('@', S); 

    while I > 0 do 
    begin 
    take := True; 
    if I > 1 then take := S[I-1] <> '"'; 
    if take then begin 
     if I < L then 
     ShowMessage(Copy(S, I + 1, L)); 
     Break; 
    end; 
    S[I] := '_'; 
    I := Pos('@', S); 
    end; 
end; 
+1

funktioniert nicht, wenn die '" 'Öffnen Tag mehr als eine Position vor' @ 'ist, oder ist der End-Tag. –

Verwandte Themen