†Sibylのお部屋†

TSVデータの分解

作成開始日 2023.02.02
最終更新日 2023.02.02

TSV形式のデータとは、項目間がタブまたはスペースで区切られた文字列データのこと。類似の形式に、カンマで区切られたCSV形式があり、一般にはこちらの方がよく利用されている。が、アプリの設定ファイルなどは、TSV形式の方が可読性が高くて便利。

DelphiではTStringListでTSVやCSVデータを扱うことができるようだが、SibylのTStringListには該当する機能がないようだ。ひょっとすると、データベース系のコンポーネントを使うと扱えるのかも知れないが、ここはごく単純に文字列処理で解決した。

基本的に、TSVデータを分解して、指定番目のデータ(文字列)を返す関数。区切りのタブ/スペースの個数は任意。データ中にスペースが含まれる場合には、当該データをシングルクォート「'」で括る。Pascal系なので文字列は「"」ではなく「'」で括る仕様(変更は簡単だと思う)。また、戻値に「'」は含まれないようにした。

//-----------------------------------------------------------------------------
  Function TForm1.SplitTSV(tsv:string; idx:Integer):String;
//-----------------------------------------------------------------------------
//TSV形式のデータを分解してn番目の項目を返す
//CSV形式には対応していないが改造は難しくないだろう
Var
  n,i  : Integer;
  buf  : String;
  flagS: Boolean;        //区切りタブ/スペース・フラグ
  flagQ: Boolean;        //シングルクォート・フラグ

Begin
  flagS:=false;
  flagQ:=false;
  i:=1;			//項目番号インジケーターを初期化
  buf:='';

  For n:=1 to Length(tsv) Do
  Begin
    If ((tsv[n]=' ')|(tsv[n]=#9))&(not flagQ) Then
    Begin
      if not flagS then inc(i);         //区間の最初の区切り文字=次の項目に
      flagS:=true;			//区切り区間であることを示すフラグ
      Continue;
    End;
    If i>idx Then Break;

    If tsv[n]=#$27 then                 //シングルクォート処理
    Begin
      flagQ:=not flagQ;			//クォート内か否かのトグルスイッチ
      Continue;				//クォート文字は無視される
    End;

    If i=idx Then buf:=buf+tsv[n];
    flagS:=false;			//区切り区間ではない=データ区間
  End;

  RESULT:=buf;
END;
使い方はこんな感じ…;なお、ソースの文字列中で「'」を使う場合は2つ重ねる。末尾で3つ重なるとエラーになるので、スペースを挟んでおく。ただし、ファイルから読み込む場合はこうした処理は不要、普通に「'」1つで括ればよい。
Var
  dat:String;
  st :String;

Begin
  dat:='.JPG  x:\tools\pmview.exe  ''/WPos=(10,400,400,340,Res) $F'' ';

  st :=SplitTSV(dat,1);	   //戻値は「.JPG」
  st :=SplitTSV(dat,2);	   //戻値は「x:\tools\pmview.exe」
  st :=SplitTSV(dat,3);	   //戻値は「/WPos=(10,400,400,340,Res) $F」

全項目の一括取得

全データを一括して取得するように改造することも難しくはない。ただし、Sibylでは動的配列が扱えないので、TStringList型を使うことになる。TStringList型変数(sl)に分解した各値が戻るので、sl[1]、sl[2]、sl[3]…の要領で各項目のデータを参照する。
//-----------------------------------------------------------------------------
  Procedure TForm1.SplitTSV2(tsv:string; sl:TStringList);
//-----------------------------------------------------------------------------
Var
  n,i  : Integer;
  buf  : String;
  flagS: Boolean;        //区切りタブ/スペース・フラグ
  flagQ: Boolean;        //シングルクォート・フラグ

Begin
  flagS:=false;
  flagQ:=false;
  i:=1;
  buf:='';
  sl.clear;
  sl.Add(tsv);           //元データ(添字を1始まりにするための調整)

  For n:=1 to Length(tsv) Do
  Begin
    If ((tsv[n]=' ')|(tsv[n]=#9))&(not flagQ) Then
    Begin
      if not flagS then begin sl.add(buf); buf:=''; inc(i); end;
      flagS:=true;
      Continue;
    End;

    If tsv[n]=#$27 then                 //シングルクォート処理
    Begin
      flagQ:=not flagQ;
      Continue;
    End;

    buf:=buf+tsv[n];
    flags:=false;
  End;
  sl.add(buf);				//これを忘れずに!
END;
使い方はこんな感じ…
Var
  sl : TStringList;		//分解したデータを格納するリスト型変数
  dat: String;			//分解するTSVデータ
  extn, prog, parm: String;	//データの各項目(拡張子、プログラム、引数)

Begin
  dat:='.JPG  x:\tools\pmview.exe  ''/WPos=(10,400,400,340,Res) $F'' ';

  sl:=TStringList.Create;
  SplitTSV2(dat, sl);

  extn:=sl[1];	//「.JPG」([0]には元データが入れてある)
  prog:=sl[2];	//「x:\tools\pmview.exe」
  parm:=sl[3];	//「/WPos=(10,400,400,340,Res) $F」

  sl.Destroy;


【Sibylのお部屋目次】 【ホーム】