- function libname(dsn)
- {
- i = index(dsn, ".");
- if (i > 0) {
- tmp = substr(dsn, 1, i - 1);
- }
- else {
- tmp = "WORK";
- }
- return toupper(tmp);
- }
- function memname(dsn)
- {
- i = index(dsn, ".");
- if (i > 0) {
- tmp = substr(dsn, i + 1, length(dsn));
- }
- else {
- tmp = dsn;
- }
- return toupper(tmp);
- }
- function ilog(path, dsn)
- {
- printf("R,%s,%s,%d,%s,%d\n", path, dsn, FNR, FILENAME, NR);
- return 1;
- }
- function olog(path, dsn)
- {
- printf("W,%s,%s,%d,%s,%d\n", path, dsn, FNR, FILENAME, NR);
- return 1;
- }
- /NOTE: ライブラリ参照名/ && /を次のように割り当てました。/ {
- libref = $3;
- getline;
- while ($1 != "物理名") {
- getline;
- }
- lib[libref] = $3;
- }
- $1 ~ /NOTE:/ && $2 ~ /データセット/ && $NF ~ /オブザベーションを読み込みました。/ {
- dsn = $3;
- libref = libname(dsn);
- mem = memname(dsn);
- if (libref != "WORK" && libref != "SASHELP") {
- dir = lib[libref];
- if (dir != "") {
- tmp = sprintf("%s/%s.sas7bdat", dir, tolower(mem));
- status = ilog(tmp, dsn);
- }
- else {
- printf("ERROR %s\n", dsn);
- exit;
- }
- }
- }
- $1 ~ /NOTE:/ && $2 ~ /データセット/ && $NF ~ /変数です。/ {
- dsn = $3;
- libref = libname(dsn);
- mem = memname(dsn);
- if (libref != "WORK" && libref != "SASHELP") {
- dir = lib[libref];
- if (dir != "") {
- tmp = sprintf("%s/%s.sas7bdat", dir, tolower(mem));
- status = olog(tmp, dsn);
- }
- else {
- printf("ERROR %s\n", dsn);
- exit;
- }
- }
- }
- $1 ~ /MPRINT\([A-Z0-9_]+\):/ && $2 ~ /^set$/ {
- match($3, /([a-zA-Z0-9_]+\.)?[a-zA-Z0-9_]+/);
- if (RLENGTH > 0) {
- dsn = substr($3, RSTART, RLENGTH);
- libref = libname(dsn);
- mem = memname(dsn);
- if (libref != "WORK" && libref != "SASHELP") {
- dir = lib[libref];
- if (dir != "") {
- tmp = sprintf("%s/%s.sas7bdat", dir, tolower(mem));
- status = ilog(tmp, dsn);
- }
- else {
- printf("ERROR %s\n", dsn);
- exit;
- }
- }
- }
- }
- END {
- print "_EOF_";
- }
SASプログラムとログを解析するユーティリティを開発するための備忘録です。This is a memo to develop utility that analyzes the SAS log.
2013年8月15日木曜日
データセットのI/Oを補足するコード(私家版#2)
これ自分用のコードです。
SASデータセットのI/Oを捕捉するコード(私家版)
SASログからI/Oを追いかける私家版のSASプログラム。入力のCSVファイルはAWKで作成しています。お客様先で大量のSASログから、入力と出力を特定するためのものです。入力ファイルで1件もデータを読まないで、僅かにMPRINTのログにしか手掛かりがないものが厄介です。
その他に、SASHELP.VTABLEを通してファイルの存在チェックをしているものなど、SASログには現れない入力があります。
その他に、SASHELP.VTABLEを通してファイルの存在チェックをしているものなど、SASログには現れない入力があります。
- /*
- *++
- * import io log-file
- *--
- */
- data iods;
- infile "c:\temp\iods.csv" dsd firstobs=2;
- attrib RW length=$1;
- attrib FILENAME length=$64;
- attrib DSN length=$32;
- attrib FNR length=8;
- attrib LOG length=$61;
- attrib NR length=8;
- input rw filename dsn fnr log nr;
- run;
- /*
- *++
- * input data-set
- *--
- */
- proc sort data=iods out=ids;
- by filename nr rw;
- run;
- data ids;
- set ids;
- by filename nr rw;
- if first.filename and rw eq 'R' then output;
- run;
- proc sort data=ids;
- by nr;
- run;
- /*
- *++
- * output data-set
- *--
- */
- proc sort data=iods out=ods;
- where rw eq 'W';
- by filename nr;
- run;
- data ods;
- set ods;
- by filename nr;
- if last.filename then output;
- run;
- proc sort data=ods;
- by nr;
- run;
- /*
- *++
- * make compare procedure statement
- *--
- */
- data _null_;
- set ods;
- attrib comment length=$256;
- attrib libstat length=$256;
- attrib titstat length=$256;
- attrib comproc length=$256;
- attrib mem length=$32;
- basedir = "/sumdata/bk02";
- comment = "/* dsn=" || compress(upcase(dsn)) || " logfile=" || compress(log) || " line=" || compress(put(fnr, best.)) || " */";
- put comment;
- i = 1;
- imax = length(filename);
- pos = 0;
- do i=1 to imax;
- if substr(filename, i, 1) eq '/' then pos = i;
- end;
- put "options nocenter;";
- libstat = "libname tmp1 '" || compress(basedir) || substr(filename, 1, pos-1) || "' access=readonly;";
- put libstat;
- libstat = "libname tmp2 '" || substr(filename, 1, pos-1) || "' access=readonly;";
- put libstat;
- titstat = "title 'dsn=" || compress(upcase(dsn)) || " log=" || compress(log) || "';";
- put titstat;
- mem = substr(dsn, index(dsn, ".")+1);
- comproc = "proc compare base=tmp1." || compress(mem) || " compare=tmp2." || compress(mem) || " maxprint=5;";
- put comproc;
- put "run;";
- put "title;";
- put ;
- run;
/* *++ * import io log-file *-- */ data iods; infile "c:\temp\iods.csv" dsd firstobs=2; attrib RW length=$1; attrib FILENAME length=$64; attrib DSN length=$32; attrib FNR length=8; attrib LOG length=$61; attrib NR length=8; input rw filename dsn fnr log nr; run; /* *++ * input data-set *-- */ proc sort data=iods out=ids; by filename nr rw; run; data ids; set ids; by filename nr rw; if first.filename and rw eq 'R' then output; run; proc sort data=ids; by nr; run; /* *++ * output data-set *-- */ proc sort data=iods out=ods; where rw eq 'W'; by filename nr; run; data ods; set ods; by filename nr; if last.filename then output; run; proc sort data=ods; by nr; run; /* *++ * make compare procedure statement *-- */ data _null_; set ods; attrib comment length=$256; attrib libstat length=$256; attrib titstat length=$256; attrib comproc length=$256; attrib mem length=$32; basedir = "/sumdata/bk02"; comment = "/* dsn=" || compress(upcase(dsn)) || " logfile=" || compress(log) || " line=" || compress(put(fnr, best.)) || " */"; put comment; i = 1; imax = length(filename); pos = 0; do i=1 to imax; if substr(filename, i, 1) eq '/' then pos = i; end; put "options nocenter;"; libstat = "libname tmp1 '" || compress(basedir) || substr(filename, 1, pos-1) || "' access=readonly;"; put libstat; libstat = "libname tmp2 '" || substr(filename, 1, pos-1) || "' access=readonly;"; put libstat; titstat = "title 'dsn=" || compress(upcase(dsn)) || " log=" || compress(log) || "';"; put titstat; mem = substr(dsn, index(dsn, ".")+1); comproc = "proc compare base=tmp1." || compress(mem) || " compare=tmp2." || compress(mem) || " maxprint=5;"; put comproc; put "run;"; put "title;"; put ; run;
登録:
投稿
(
Atom
)