Link to home
Start Free TrialLog in
Avatar of wantime
wantime

asked on

Delphi2010: How to split string which contains space and " "

hi all,

i have a string as followed:

Test01:"C:\with a space\anything_here"  Test02:"C:\with a space\with a space\anything_here"  Test03:C:\without\a\space

how do i split it into a array which contains following three element:
Test01:"C:\with a space\anything_here"
Test02:"C:\with a space\with a space\anything_here"
Test03:C:\without\a\space

i have tried to split the string, but i get just following parts:
Test01:"C:\with
a
space\anything_here"

any suggestion is appreciate. I would like to use " " and blank space to split the string.
thanks,

wantime
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure Split(Delimiter: Char; Str: string; ListOfStrings: TStrings) ;
  private

  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  commands: TStringList;
begin
  commands := TStringList.Create;
  Split(' ', Edit1.Text, commands) ;
  Edit2.Text := commands[0];
  Edit3.Text := commands[1];
  Edit4.Text := commands[2];
end;

procedure TForm1.Split(Delimiter: Char; Str: string; ListOfStrings: TStrings) ;
begin
   ListOfStrings.Clear;
   ListOfStrings.Delimiter     := Delimiter;
   ListOfStrings.DelimitedText := Str;
end;


end.

Open in new window

Avatar of Ephraim Wangoya
Ephraim Wangoya
Flag of United States of America image

try this
procedure TForm1.Button1Click(Sender: TObject);
var
  commands: TStringList;
begin
  commands := TStringList.Create;
  Split(Edit1.Text, commands) ;
  Edit2.Text := commands[0];
  Edit3.Text := commands[1];
  Edit4.Text := commands[2];
  commands.Free;
end

procedure TForm1.Split(Str: string; ListOfStrings: TStrings) ;
var
  temp: string;
  I: integer;
begin
  ListOfStrings.Clear;
  ListOfStrings.Delimiter := ',';
  ListOfStrings.StrictDelimiter := True;
  ListOfStrings.QuoteChar := '"';
  ListOfStrings.DelimitedText := Str;

  temp := StringReplace(Str, 'Test', ',Test', [rfReplaceAll]);
  if temp[1] = ',' then
    temp[1] := ' ';

  ListOfStrings.DelimitedText := Trim(temp);
end;

Open in new window

Sorry, I assigned it twice
procedure TForm1.Button1Click(Sender: TObject);
var
  commands: TStringList;
begin
  commands := TStringList.Create;
  Split(Edit1.Text, commands) ;
  Edit2.Text := commands[0];
  Edit3.Text := commands[1];
  Edit4.Text := commands[2];
  commands.Free;
end

procedure TForm1.Split(Str: string; ListOfStrings: TStrings) ;
var
  temp: string;
  I: integer;
begin
  ListOfStrings.Clear;
  ListOfStrings.Delimiter := ',';
  ListOfStrings.StrictDelimiter := True;
  ListOfStrings.QuoteChar := '"';

  temp := StringReplace(Trim(Str), 'Test', ',Test', [rfReplaceAll]);
  if temp[1] = ',' then
    temp[1] := ' ';

  ListOfStrings.DelimitedText := Trim(temp);
end;

Open in new window

Avatar of jimyX
jimyX

Is your format constant? Is it always going to be Test01, Test02, Test03,...etc?
uses StrUtils;

procedure TForm1.Button1Click(Sender: TObject);
var
  strlst:TStrings;
  Str:String;
  i:integer;
begin
  str:='Test01:"C:\with a space\anything_here"  Test02:"C:\with a space\with a space\anything_here"  Test03:C:\without\a\space';
  strlst:=TStringlist.Create;
  i:=2;

  repeat
    strlst.Add(copy(str,1,pos('Test'+Format('%.2d', [i])+':',str)-3));
    delete(str,1,pos('Test'+Format('%.2d', [i])+':',str)-1);
    inc(i);
  until posex('Test',str,3) <= 0;

  strlst.Add(copy(str,1,length(str)));
  delete(str,1,length(str));

  showmessage(strlst.Text);
  strlst.Free;
end;

Open in new window

use a different delimiter
do not use space as delimiter

this is same as if somebody asks you to count words in a document when somebody else has put a space between each 2 letters
you will ask them to remove extra spaces or use something else to delimit by

If you will not have an identifier such as "TestX" in your examples, then use a proper delimiter as Geert mentioned above
You could use a semicolon and set StrictDelimiter to True
1. replace all '" Test' with '"^Test' and store the resulting string in a TStringList
2. use the .DelimitedText property of the TStringList with a '^' character as the delimiter, placing the result in another TStringList variable.
Avatar of wantime

ASKER

thank you for your answer.

as i mentioned, I would like to use " " and blank space to split the string.

"Test" is just a example, they can also be different. just like:

X:"C:\with a space\anything_here"  Y:"C:\with a space\with a space\anything_here"  Z:C:\without\a\space

the thing i am sure it that between each block there exist a blank. If this block has space in it, symbol " " will then be used.

Avatar of wantime

ASKER

btw, symbol " " will be used, only if there are space in block. If there is no space in the block, " " will not be used.

first and second space has blank, so " " is used.

X:"C:\with a space\anything_here"  Y:"C:\with a space\with a space\anything_here"

the third one doesn't has space , so it looks like Z:C:\without\a\space

if there is a method to make the block which has space as a unit, then the whole string should be possible to be splited by using space as delimiter.
using StrictDelimiter is the easiest

how do you fill up your stringlist  ?

function Test: string;
var X, Y: TStrings;
begin
  X := TStringList.Create;
  Y := TStringList.Create;
  try
    X.Delimiter := ' ';
    Y.Delimiter := ' ';
    X.StrictDelimiter := True;
    Y.StrictDelimiter := True;
    X.Add('test 1');
    X.Add('test 2');
    Y.Add(X.DelimitedText);
    X.Clear;
    X.Add('test 3');
    X.Add('test 4);
    Y.Add(X.DelimitedText);
    Result := Y.DelimitedText;
  finally
    Y.Free;
    X.Free;
  end;
end;
ASKER CERTIFIED SOLUTION
Avatar of jimyX
jimyX

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
forgot to post the output:
 
Memo1
Result of buildstring: 
"""TEST1=C:\with a space\anything_here"" ""TEST2=C:\with a space\with a space\anything_here"" TEST3=C:\without\a\space" """TEST4=C:\with a space\anything_here"" ""TEST5=C:\with a space\with a space\anything_here"" TEST6=C:\without\a\space"
Result of split string
TEST1=C:\with a space\anything_here
TEST2=C:\with a space\with a space\anything_here
TEST3=C:\without\a\space
TEST4=C:\with a space\anything_here
TEST5=C:\with a space\with a space\anything_here
TEST6=C:\without\a\space
Extracting specific values : 
TEST1 = "C:\with a space\anything_here"

Open in new window

Avatar of wantime

ASKER

sorry, i should explain my question more clear.

the string which need to be splited is not constant, but they have a format like followed:

Format I:

[A-Z][:]["][A-Z and space]["]

Format II:

[A-Z][:][A-Z]

that means, "Test01,Test02, Test03" and "X, Y, Z" that i mentioned above is just a example, the length of the word changed. The background info for this question are followed: In a text field one could input differnt Commands, these Commands is seperated by space. If Command contains space, Format I will be used, if not, Format II will be used. The format is there and i could not change it. what  I need to resolve is to splite the whole string into differnt rows/block like i mentioned before. (after the string is splited, an application will be called to execute each Command. But this is another topic which we don't need to discuss here.)
@Delphi experts

Since you're working with paths, it is possible for a path to contain two consecutive spaces (or more) and still be a legal path.

You should probably test the possibility of the no-spaces path not being the last one in the input string.

======
@wantime

Will you support UNC paths or will you always have a drive letter?

Path names can contain characters other than A-Z.  Your pattern definition is incomplete.
i'm lost, you are asking something completely different now ?

if you care to be precise with your question ...
you will get an acurate and precise answer

this is making it difficult to follow !
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of wantime

ASKER

At the begin i was not sure, what the format should be look like. your suggestion have already help to resolve the problem, after i redefine the format in my codes.