2023年4月11日火曜日

JSONのファイルから32KBを超えるSASプログラムを抽出する。

LIBNAMEのJSONエンジンの欠点は、32KBを超える長さのデータを抽出できない点です。できないものは仕方ないので、32KBを超えてもSASプログラムを抽出するコードを書きました。 字句解析の状態遷移を考えて "code": の値を抽出してバックスラッシュのエンコードを解いてファイルの保存します。入力のJSONファイルは整形されていないコンパクトや書式の前提です。昔、Lex, Yaccを使っていた記憶を掘り起こした。

  1. /* Code extraction from JSON file of job definition */  
  2. %macro extractJobCode(infile=, outfile=, debug=0);  
  3.     %local/readonly DQ='22'x;  
  4.     %local/readonly BSL='5c'x;  
  5.     %local/readonly BS='08'x;  
  6.     %local/readonly FF='0c'x;  
  7.     %local/readonly NL='0a'x;  
  8.     %local/readonly CR='0d'x;  
  9.     %local/readonly TB='09'x;  
  10.     %local/readonly SP='20'x;  
  11.   
  12.     data _NULL_;  
  13.         attrib filein length=8 label='input file id';  
  14.         attrib fileid length=8 label='output file id';  
  15.         attrib stat length=8 label='State of lexical analysis';  
  16.         attrib token length=$256 label='Token';  
  17.         attrib ucode length=$4 label='Unicode';  
  18.         attrib count length=8;  
  19.   
  20.         /* Open input/output files */  
  21.         filein=fopen("&infile" , 'I'1'B');  
  22.         fileid=fopen("&outfile", 'O'1'B');  
  23.         count=0;  
  24.         stat=0;  
  25.         rec=&SP;  
  26.   
  27.         do while(fread(filein)=0);  
  28.             rc=fget(filein, rec, 1);  
  29.   
  30.             %if &debug=1 %then  
  31.                 %do;  
  32.   
  33.                     if count < 512 then  
  34.                         put stat=rec=token=;  
  35.                     count=count + 1;  
  36.                 %end;  
  37.   
  38.             if stat eq 0 and rec eq &DQ then  
  39.                 stat=1;  
  40.             else if stat eq 1 then  
  41.                 do;  
  42.   
  43.                     if rec eq &DQ then  
  44.                         do;  
  45.   
  46.                             /* Double quotes */  
  47.                             if token eq 'code' then  
  48.                                 stat=2;  
  49.                             else  
  50.                                 stat=0;  
  51.                             token='';  
  52.                         end;  
  53.                     else  
  54.                         do;  
  55.                             token=catt(token, rec);  
  56.                             stat=1;  
  57.                         end;  
  58.                 end;  
  59.             else if stat eq 2 then  
  60.                 do;  
  61.   
  62.                     if rec in (&SP, &TB, &NL) then  
  63.                         stat=2;  
  64.                     else if rec eq ':' then  
  65.                         stat=3;  
  66.                     else  
  67.                         stat=0;  
  68.                 end;  
  69.             else if stat eq 3 then  
  70.                 do;  
  71.   
  72.                     if rec in (&SP, &TB, &NL) then  
  73.                         stat=3;  
  74.                     else if rec eq &DQ then  
  75.                         stat=4;  
  76.                     else  
  77.                         stat=0;  
  78.                 end;  
  79.             else if stat eq 4 then  
  80.                 do;  
  81.   
  82.                     if rec eq &DQ then  
  83.                         stat=0;  
  84.                     else if rec eq &BSL then  
  85.                         stat=5;  
  86.                     else  
  87.                         do;  
  88.                             rc=fput(fileid, rec);  
  89.                             rc=fwrite(fileid);  
  90.                         end;  
  91.                 end;  
  92.             else if stat eq 5 then  
  93.                 do;  
  94.   
  95.                     /* Handling of backslash-escaped characters */  
  96.                     if rec eq 'b' then  
  97.                         do;  
  98.                             rc=fput(fileid, &BS);  
  99.                             rc=fwrite(fileid);  
  100.                             stat=4;  
  101.                         end;  
  102.                     else if rec eq &DQ then  
  103.                         do;  
  104.                             rc=fput(fileid, &DQ);  
  105.                             rc=fwrite(fileid);  
  106.                             stat=4;  
  107.                         end;  
  108.                     else if rec eq &BSL then  
  109.                         do;  
  110.                             rc=fput(fileid, &BSL);  
  111.                             rc=fwrite(fileid);  
  112.                             stat=4;  
  113.                         end;  
  114.                     else if rec eq 'f' then  
  115.                         do;  
  116.                             rc=fput(fileid, &FF);  
  117.                             rc=fwrite(fileid);  
  118.                             stat=4;  
  119.                         end;  
  120.                     else if rec eq 'n' then  
  121.                         do;  
  122.                             rc=fput(fileid, &NL);  
  123.                             rc=fwrite(fileid);  
  124.                             stat=4;  
  125.                         end;  
  126.                     else if rec eq 'r' then  
  127.                         do;  
  128.                             rc=fput(fileid, &CR);  
  129.                             rc=fwrite(fileid);  
  130.                             stat=4;  
  131.                         end;  
  132.                     else if rec eq 't' then  
  133.                         do;  
  134.                             rc=fput(fileid, &TB);  
  135.                             rc=fwrite(fileid);  
  136.                             stat=4;  
  137.                         end;  
  138.                     else if rec eq 'u' then  
  139.                         do;  
  140.                             ucode='';  
  141.                             do i=1 to 4;  
  142.                                 rc=fread(filein);  
  143.                                 rc=fget(filein, rec, 1);  
  144.                                 ucode=catt(ucode, rec);  
  145.                             end;  
  146.                             if ucode eq '0026' then  
  147.                                 do;  
  148.                                     rc=fput(fileid, '&');  
  149.                                     rc=fwrite(fileid);  
  150.                                 end;  
  151.                             else if ucode eq '003c' then  
  152.                                 do;  
  153.                                     rc=fput(fileid, '<');  
  154.                                     rc=fwrite(fileid);  
  155.                                 end;  
  156.                             else if ucode eq '003e' then  
  157.                                 do;  
  158.                                     rc=fput(fileid, '>');  
  159.                                     rc=fwrite(fileid);  
  160.                                 end;  
  161.                             else  
  162.                                 do;  
  163.                                     rc=fput(fileid, &BSL);  
  164.                                     rc=fput(fileid, 'u');  
  165.                                     rc=fput(fileid, ucode);  
  166.                                     rc=fwrite(fileid);  
  167.                                 end;  
  168.                             stat=4;  
  169.                         end;  
  170.                 end;  
  171.         end;  
  172.   
  173.         /* Close input/output files */  
  174.         rc=fclose(filein);  
  175.         rc=fclose(fileid);  
  176.     run;  
  177.   
  178. %mend;  

1 件のコメント :

  1. &、>、< がエンコードされていることがあったので、コードを直しました。

    返信削除