2013年8月15日木曜日

データセットのI/Oを補足するコード(私家版#2)

これ自分用のコードです。

  1. function libname(dsn)  
  2. {  
  3.         i = index(dsn, ".");  
  4.         if (i > 0) {  
  5.                 tmp = substr(dsn, 1, i - 1);  
  6.         }  
  7.         else {  
  8.                 tmp = "WORK";  
  9.         }  
  10.         return toupper(tmp);  
  11. }  
  12.   
  13. function memname(dsn)  
  14. {  
  15.         i = index(dsn, ".");  
  16.         if (i > 0) {  
  17.                 tmp = substr(dsn, i + 1, length(dsn));  
  18.         }  
  19.         else {  
  20.                 tmp = dsn;  
  21.         }  
  22.         return toupper(tmp);  
  23. }  
  24.   
  25. function ilog(path, dsn)  
  26. {  
  27.         printf("R,%s,%s,%d,%s,%d\n", path, dsn, FNR, FILENAME, NR);  
  28.         return 1;  
  29. }  
  30.   
  31. function olog(path, dsn)  
  32. {  
  33.         printf("W,%s,%s,%d,%s,%d\n", path, dsn, FNR, FILENAME, NR);  
  34.         return 1;  
  35. }  
  36.   
  37. /NOTE: ライブラリ参照名/ && /を次のように割り当てました。/ {  
  38.         libref = $3;  
  39.         getline;  
  40.         while ($1 != "物理名") {  
  41.                 getline;  
  42.         }  
  43.         lib[libref] = $3;  
  44.   
  45. }  
  46.   
  47. $1 ~ /NOTE:/ && $2 ~ /データセット/ && $NF ~ /オブザベーションを読み込みました。/ {  
  48.         dsn = $3;  
  49.         libref = libname(dsn);  
  50.         mem = memname(dsn);  
  51.   
  52.         if (libref != "WORK" && libref != "SASHELP") {  
  53.                 dir = lib[libref];  
  54.                 if (dir != "") {  
  55.                         tmp = sprintf("%s/%s.sas7bdat", dir, tolower(mem));  
  56.                         status = ilog(tmp, dsn);  
  57.                 }  
  58.                 else {  
  59.                         printf("ERROR %s\n", dsn);  
  60.                         exit;  
  61.                 }  
  62.         }  
  63. }  
  64.   
  65. $1 ~ /NOTE:/ && $2 ~ /データセット/ && $NF ~ /変数です。/ {  
  66.         dsn = $3;  
  67.         libref = libname(dsn);  
  68.         mem = memname(dsn);  
  69.   
  70.         if (libref != "WORK" && libref != "SASHELP") {  
  71.                 dir = lib[libref];  
  72.                 if (dir != "") {  
  73.                         tmp = sprintf("%s/%s.sas7bdat", dir, tolower(mem));  
  74.                         status = olog(tmp, dsn);  
  75.                 }  
  76.                 else {  
  77.                         printf("ERROR %s\n", dsn);  
  78.                         exit;  
  79.                 }  
  80.         }  
  81. }  
  82.   
  83. $1 ~ /MPRINT\([A-Z0-9_]+\):/ && $2 ~ /^set$/ {  
  84.         match($3, /([a-zA-Z0-9_]+\.)?[a-zA-Z0-9_]+/);  
  85.         if (RLENGTH > 0) {  
  86.                 dsn = substr($3, RSTART, RLENGTH);  
  87.                 libref = libname(dsn);  
  88.                 mem = memname(dsn);  
  89.                 if (libref != "WORK" && libref != "SASHELP") {  
  90.                         dir = lib[libref];  
  91.                         if (dir != "") {  
  92.                                 tmp = sprintf("%s/%s.sas7bdat", dir, tolower(mem));  
  93.                                 status = ilog(tmp, dsn);  
  94.                         }  
  95.                         else {  
  96.                                 printf("ERROR %s\n", dsn);  
  97.                                 exit;  
  98.                         }  
  99.                 }  
  100.         }  
  101. }  
  102.   
  103. END {  
  104.         print "_EOF_";  
  105. }  

SASデータセットのI/Oを捕捉するコード(私家版)

SASログからI/Oを追いかける私家版のSASプログラム。入力のCSVファイルはAWKで作成しています。お客様先で大量のSASログから、入力と出力を特定するためのものです。入力ファイルで1件もデータを読まないで、僅かにMPRINTのログにしか手掛かりがないものが厄介です。
その他に、SASHELP.VTABLEを通してファイルの存在チェックをしているものなど、SASログには現れない入力があります。

  1. /*  
  2. *++  
  3. * import io log-file  
  4. *--  
  5. */  
  6.   
  7. data iods;  
  8.  infile "c:\temp\iods.csv" dsd firstobs=2;  
  9.  attrib RW length=$1;  
  10.  attrib FILENAME length=$64;  
  11.  attrib DSN length=$32;  
  12.  attrib FNR length=8;  
  13.  attrib LOG length=$61;  
  14.  attrib NR length=8;  
  15.  input rw filename dsn fnr log nr;  
  16. run;  
  17.   
  18. /*  
  19. *++  
  20. * input data-set  
  21. *--  
  22. */  
  23.   
  24. proc sort data=iods out=ids;  
  25.  by filename nr rw;  
  26. run;  
  27.   
  28. data ids;  
  29.  set ids;  
  30.  by filename nr rw;  
  31.  if first.filename and rw eq 'R' then output;  
  32. run;  
  33.   
  34. proc sort data=ids;  
  35.  by nr;  
  36. run;  
  37.   
  38.   
  39. /*  
  40. *++  
  41. * output data-set  
  42. *--  
  43. */  
  44.   
  45. proc sort data=iods out=ods;  
  46.  where rw eq 'W';  
  47.  by filename nr;  
  48. run;  
  49.   
  50. data ods;  
  51.  set ods;  
  52.  by filename nr;  
  53.  if last.filename then output;  
  54. run;  
  55.   
  56. proc sort data=ods;  
  57.  by nr;  
  58. run;  
  59.   
  60. /*  
  61. *++  
  62. * make compare procedure statement  
  63. *--  
  64. */  
  65.   
  66. data _null_;  
  67.  set ods;  
  68.  attrib comment length=$256;  
  69.  attrib libstat length=$256;  
  70.  attrib titstat length=$256;  
  71.  attrib comproc length=$256;  
  72.  attrib mem length=$32;  
  73.   
  74.  basedir = "/sumdata/bk02";  
  75.   
  76.  comment = "/* dsn=" || compress(upcase(dsn)) || " logfile=" || compress(log) || " line=" || compress(put(fnr, best.)) || " */";  
  77.  put comment;  
  78.   
  79.  i = 1;  
  80.  imax = length(filename);  
  81.  pos = 0;  
  82.   
  83.  do i=1 to imax;  
  84.   if substr(filename, i, 1) eq '/' then pos = i;  
  85.  end;  
  86.   
  87.  put "options nocenter;";  
  88.  libstat = "libname tmp1 '" || compress(basedir) || substr(filename, 1, pos-1) || "' access=readonly;";  
  89.  put libstat;  
  90.   
  91.  libstat = "libname tmp2 '" || substr(filename, 1, pos-1) || "' access=readonly;";  
  92.  put libstat;  
  93.   
  94.  titstat = "title 'dsn=" || compress(upcase(dsn)) || " log=" || compress(log) || "';";  
  95.  put titstat;   
  96.   
  97.  mem = substr(dsn, index(dsn, ".")+1);  
  98.  comproc = "proc compare base=tmp1." || compress(mem) || " compare=tmp2." || compress(mem) || " maxprint=5;";  
  99.  put comproc;  
  100.  put "run;";  
  101.  put "title;";  
  102.  put ;  
  103.   
  104. run;