12

How can I split a string in Inno Setup?
Is there any special function in Inno Setup to split the string?

I want to get the following from the string '11.2.0.16':

tokens: array of string = ('11', '0', '2', '16');

Thanks in advance!

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
srikanth1267
  • 123
  • 1
  • 1
  • 7

4 Answers4

20

For anyone who prefers the function format, I have modified @cezarlamann's answer:

function StrSplit(Text: String; Separator: String): TArrayOfString;
var
  i, p: Integer;
  Dest: TArrayOfString; 
begin
  i := 0;
  repeat
    SetArrayLength(Dest, i+1);
    p := Pos(Separator,Text);
    if p > 0 then begin
      Dest[i] := Copy(Text, 1, p-1);
      Text := Copy(Text, p + Length(Separator), Length(Text));
      i := i + 1;
    end else begin
      Dest[i] := Text;
      Text := '';
    end;
  until Length(Text)=0;
  Result := Dest
end;
Matthieu
  • 2,736
  • 4
  • 57
  • 87
timyhac
  • 373
  • 3
  • 9
13

I've been looking for the same thing today...

This one works just fine on Inno Setup Scripts. Paste this excerpt inside your script before the procedure/function which will call this "split" procedure.

You can also modify this onto a function, if you desire...

procedure Explode(var Dest: TArrayOfString; Text: String; Separator: String);
var
  i, p: Integer;
begin
  i := 0;
  repeat
    SetArrayLength(Dest, i+1);
    p := Pos(Separator,Text);
    if p > 0 then begin
      Dest[i] := Copy(Text, 1, p-1);
      Text := Copy(Text, p + Length(Separator), Length(Text));
      i := i + 1;
    end else begin
      Dest[i] := Text;
      Text := '';
    end;
  until Length(Text)=0;
end;

procedure Whatever();
var 
  str: String;
  strArray: TArrayOfString;
  i: Integer;
begin
  Explode(strArray,str,'.');
  for i:=0 to GetArrayLength(strArray)-1 do begin
    { do something }
  end;
end;

Taken from here

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
cezarlamann
  • 1,465
  • 2
  • 28
  • 43
  • Just out of curiosity, [`here's`](http://pastebin.com/STcQLfKR) tricky alternative which replaces all separator chars by line breaks and load such text to a string list which automatically breaks the values into items. But anyway, that's not all. You need to strip that substring to be parsed from the original string, and finally remove quotes from the values and format those values into a dotted string (hence my initial comment about "split"). – TLama May 23 '14 at 21:19
3

Here's what I use:

procedure SplitString(S, Delim: string; var Dest: TArrayOfString);
var
  Temp: string;
  I, P: Integer;
begin
  Temp := S;
  I := StringChangeEx(Temp, Delim, '', true);
  SetArrayLength(Dest, I + 1);
  for I := 0 to GetArrayLength(Dest) - 1 do
  begin
    P := Pos(Delim, S);
    if P > 0 then
    begin
      Dest[I] := Copy(S, 1, P - 1);
      Delete(S, 1, P + Length(Delim) - 1);
    end
    else
      Dest[I] := S;
  end;
end;

This version avoids repeated array resizing by counting the delimiters using StringChangeEx and setting the array size only once. Since we then know the array size, we can just use a for loop. I also opted for Delete rather than Copy, which (IMO) makes the code easier to read. (This version also fixes the bug where the split does not occur correctly if the delimiter is longer than 1 character.)

Bill_Stewart
  • 22,916
  • 4
  • 51
  • 62
1

If there is a possibility that the delimiter could also be right at the end of the string, then this is what I used (modified from @timyha's answer)

function StrSplit(Text: String; Separator: String): TArrayOfString;
var
  i, p: Integer;
  Dest: TArrayOfString; 
begin
  i := 0;
  repeat
    SetArrayLength(Dest, i+1);
    p := Pos(Separator,Text);

    if p > 0 then begin
      Dest[i] := Copy(Text, 1, p-1);
      Text := Copy(Text, p + Length(Separator), Length(Text));
      i := i + 1;
      
      //add an empty string if delim was at the end 
         
      if Text = '' then begin
        Dest[i]:=''; 
        i := i + 1;
      end;

    end else begin
      Dest[i] := Text;
      Text := '';
    end;
  until Length(Text)=0;
  Result := Dest
end;
S. Francis
  • 119
  • 5