Extract string from a text file using 2 delimiters

2019-02-06 16:35发布

问题:

I'm trying to extract a string from a text file using 2 delimiters. One to start and one to stop.

Example:

Hi my name is$John and I'm happy/today

What I need to do is to call a function that would return the string between $ and /. I've been looking everywhere but I can't seem to find something useful and I'm new to programming.

回答1:

You can do it with Pos and Copy:

function ExtractText(const Str: string; const Delim1, Delim2: char): string;
var
  pos1, pos2: integer;
begin
  result := '';
  pos1 := Pos(Delim1, Str);
  pos2 := Pos(Delim2, Str);
  if (pos1 > 0) and (pos2 > pos1) then
    result := Copy(Str, pos1 + 1, pos2 - pos1 - 1);
end;


回答2:

The above functions won't work if the 2nd text is also appearing before the 1st pattern...

You should use PosEx() instead of Pos():

You can do it with Pos and Copy:

function ExtractText(const Str: string; const Delim1, Delim2: string): string;
var
  pos1, pos2: integer;
begin
  result := '';
  pos1 := Pos(Delim1, Str);
  if pos1 > 0 then begin
    pos2 := PosEx(Delim2, Str, pos1+1);
    if pos2 > 0 then
      result := Copy(Str, pos1 + 1, pos2 - pos1 - 1);
  end;
end;


回答3:

I'd do it something like this:

function ExtractDelimitedString(const s: string): string;
var
  p1, p2: Integer;
begin
  p1 := Pos('$', s);
  p2 := Pos('/', s);
  if (p1<>0) and (p2<>0) and (p2>p1) then begin
    Result := Copy(s, p1+1, p2-p1-1);
  end else begin
    Result := '';//delimiters not found, or in the wrong order; raise error perhaps
  end;
end;


回答4:

Get em all

function ExtractText(const Str: string; const Delim1, Delim2: string): TStringList;
var
  c,pos1, pos2: integer;
begin
  result:=TStringList.Create;
  c:=1;
  pos1:=1;

  while pos1>0 do
  begin
    pos1 := PosEx(Delim1, Str,c);
    if pos1 > 0 then begin
      pos2 := PosEx(Delim2, Str, pos1+1);
    if pos2 > 0 then
      result.Add(Copy(Str, pos1 + length(delim1), pos2 - (length(delim1) + pos1)));
      c:=pos1+1;
     end;

  end;
end;


回答5:

Gab, you can write a function to do this using a TFileStream class, and the Copy and Pos functions.

see this sample :

uses
  Classes,
  SysUtils;

function ExtractString(Const FileName: TFileName;Const IDel,FDel : AnsiString) : AnsiString;
Var
 FileStream : TFileStream;
 i,f        : Integer;
begin
  FileStream:= TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); //oopen the file
  try
    try
      SetLength(Result, FileStream.Size); //set the size of the string
      FileStream.Read(Pointer(Result)^, FileStream.Size);//read the content into a string
      i:=Pos(IDel,Result);//search the initial delimiter
      f:=Pos(FDel,Result);//search the final delimiter
      Result:=Copy(Result,i+1,f-i-1); //extract the value between the delimiters
    except
      Result := '';
      raise;
    end;
  finally
    FileStream.Free;
  end;
end;

and use in this way

ExtractString('your_file_name','$','/');


回答6:

In the newer Delphi's you can do it like this.. (yay)

program Project40; {$APPTYPE CONSOLE}

uses RegularExpressions;

const
  str = 'Is$John and I''m happy/today';

function GetStr(const aStr: string): string;
begin
  Result := TRegEx.Match(aStr, '\$.*/').Value;
  Result := Copy(Result, 2, Length(Result) - 2);
end;

begin
  Writeln(GetStr(str));
  ReadLn;
end.


回答7:

Assuming both delimiters are single characters as per your post:

function ExtractDelimitedValueFromFile(const aFilename: String;
                                       const aOpenDelim: Char;
                                       const aCloseDelim: Char;
                                       var aValue: String): Boolean;
var
  i: Integer;
  strm: TStringStream;
  delimStart: Integer;
  delimEnd: Integer;
begin
  result      := FALSE;
  aValue      := '';
  delimStart  := -1;
  delimEnd    := -1;

  strm := TStringStream.Create;
  try
    strm.LoadFromFile(aFileName);

    for i := 1 to strm.Size do
    begin
      if (delimStart = -1) and (strm.DataString[i] = aOpenDelim) then
        delimStart := i
      else if (delimStart <> -1) and (strm.DataString[i] = aCloseDelim) then
        delimEnd := i;

      result := (delimStart <> -1) and (delimEnd <> -1);
      if result then
      begin
        aValue := Copy(strm.DataString, delimStart + 1, delimEnd - delimStart - 1);
        BREAK;
      end;
    end;

  finally
    strm.Free;
  end;
end;

Usage:

  var
    str: String;
  begin
    if ExtractDelimitedValueFromFile('path\filename.ext', '$', '/', str) then
      // work with str
    else
      // delimited value not found in file
  end;