前のエントリのコメント欄で希望のあった、
call executeについても、わかりにくいですね。putでコード生成して、%includeで実行って方法、聞いたことはありましたが、まだ自分でやったことはありませんでした。ぜひコード例を紹介していただけたら嬉しいです。
SASマクロプログラムの要諦 - The Nameless City
の話。
生成されるプログラムを予めテキストファイルに出力しておき、それを%includeで読み込む。
話としては全く難しくはない。
データセットの中身をファイルに出力する方法は幾つかあるが、
そのウチの一つに、dataステップ内でfileステートメントで出力先を設定し、putで出力する方法がある。
書き出し。
通常、putステートメントは、Log出力に指定した内容あるいは中身を出力する。
data _null_ ;
put 'Hello! World' ;
run ;
1 data _null_ ;
2 put 'Hello! World' ;
3 run ;
Hello! World
NOTE: DATAステートメント処理(合計処理時間):
処理時間 0.14 秒
CPU時間 0.01 秒
「何も指定していない場合には」。
つまりは、指定する事によって、出力先は変更可能である(この、変更可能である、という所が要諦の一つになる。カンのいい人は、「ストリーム出力だ!」とか、「じゃ、出力デバイス指定出きんじゃね?」とか考えれば、回答が直ぐに思いつくだろう)。
ata _null_ ;
file "%sysfunc(sysget(temp))\test.txt" lrecl=32767;
a='Hello! World' ;
put a a ;
run ;
fileステートメントは、まあ使った事のない人は幾らかいると思うが、infileステートメントの逆だと考えてればいい。通常はテキストファイルを決まった形式で書き出す、ぐらいで考えて使えば良い。
fileステートメントの細かいオプションはヘルプ参照の事、だけど、今回のプログラム書き出すパターンではほぼほぼlrecl=32767の拡張ぐらいしか使わない(逆にこれは設定しておくのが無難)。
細かいながら、putステートメントでの注意点を一つ。このステートメント内には、リテラルか変数ぐらいしか指定できない(変数に付随するフォーマットは設定出来るが)。また、文字列リテラルを2つ並べても、一つの文字列として扱われる(例えば「put 'Hello! World' 'Hello! World' ;」としても、出力では「Hello! WorldHello! World」になる)。
NOTE: 出力ファイル"C:\Users\~~~\AppData\Local\Temp\test.txt" : ファイル名=C:\Users\~~~\AppData\Local\Temp\test.txt, レコードフォーマット=V,論理レコード長=32767, ファイルサイズ (バイト)=0, 更新日時=2014年12月02日 23時23分18秒, 作成日時=2014年12月02日 23時04分04秒 NOTE: 1レコードを出力ファイル"C:\Users\~~~\AppData\Local\Temp\test.txt"に書き込みました・ 最小レコード長は25です。 最大レコード長は25です。 NOTE: DATAステートメント処理(合計処理時間): 処理時間 0.09 秒 CPU時間 0.09 秒
Hello! World Hello! World
(デフォルトの区切り文字は半角空白)
デバック時には、
data _null_ ;
file log ;
a='Hello! World' ;
put a a ;
run ;
(ログ出力)
data _null_ ;
file log ;
a='Hello! World' ;
put a a ;
run ;
(標準出力)
読み込み。
%include、以上、なのだが、まあ注意点としては、
「実行プログラムとして読み込まれる」のと、「オープンコードとして読み込まれる」という事ぐらいかなあ。
例えばこれがマクロ内で読み込みされてもそのマクロ内で生成されたSASマクロ変数なんかは参照出来ない。*1
options source2 ;
ods listing ;
filename _RSAS "%sysfunc(pathname(WORK))/temp.sas" lrecl=32767 ;
data _null_ ;
attrib TMPSTR length=$1000. ;
file _RSAS ;
TMPSTR = 'proc datasets ' ;
put TMPSTR ;
TMPSTR = 'nolist' ;
put +4 TMPSTR ;
TMPSTR = ';' ;
put TMPSTR ;
TMPSTR = 'contents' ;
put +4 TMPSTR ;
TMPSTR = 'data=sashelp.iris' ;
put +8 TMPSTR ;
TMPSTR = 'varnum' ;
put +8 TMPSTR ;
TMPSTR = ';' ;
put +4 TMPSTR ;
TMPSTR = 'quit ;' ;
put TMPSTR ;
run ;
%include _RSAS ;
ods listing close ;
408
409 options source2 ;
410 ods listing ;
411
412
413 filename _RSAS "%sysfunc(pathname(WORK))/temp.sas" lrecl=32767 ;
414 data _null_ ;
415 attrib TMPSTR length=$1000. ;
416 file _RSAS ;
417 TMPSTR = 'proc datasets ' ;
418 put TMPSTR ;
419 TMPSTR = 'nolist' ;
420 put +4 TMPSTR ;
421 TMPSTR = ';' ;
422 put TMPSTR ;
423 TMPSTR = 'contents' ;
424 put +4 TMPSTR ;
425 TMPSTR = 'data=sashelp.iris' ;
426 put +8 TMPSTR ;
427 TMPSTR = 'varnum' ;
428 put +8 TMPSTR ;
429 TMPSTR = ';' ;
430 put +4 TMPSTR ;
431 TMPSTR = 'quit ;' ;
432 put TMPSTR ;
433 run ;
NOTE: 出力ファイル_RSAS :
ファイル名=C:\Users\~~~\AppData\Local\Temp\SAS Temporary Files\_TD8700_~~~_\temp.sas,
レコードフォーマット=V,論理レコード長=32767,
ファイルサイズ (バイト)=0,
更新日時=2014年12月03日 00時45分22秒,
作成日時=2014年12月03日 00時26分12秒
NOTE: 8レコードを出力ファイル_RSASに書き込みました。
最小レコード長は1です。
最大レコード長は25です。
NOTE: DATAステートメント処理(合計処理時間):
処理時間 0.03 秒
CPU時間 0.01 秒
434
435 %include _RSAS ;
NOTE: %INCLUDE (レベル1)ファイル_RSASはファイルC:\Users\~~~\AppData\Local\Temp\SAS Temporary Files\_TD8700_~~~_\temp.sasです。
436 +proc datasets
NOTE: HTML Bodyファイルの書き込み先: sashtml4.htm
437 + nolist
438 +;
439 + contents
440 + data=sashelp.iris
441 + varnum
442 + ;
443 +quit ;
NOTE: PROCEDURE DATASETS処理(合計処理時間):
処理時間 0.89 秒
CPU時間 0.78 秒
NOTE: %INCLUDE (レベル1)を終了します。
444
445
446 ods listing close ;
SAS システム 2014年12月 2日 DATASETS プロシジャ データセット名 SASHELP.IRIS オブザベーション数 150 メンバータイプ DATA 変数の数 5 エンジン V9 インデックス数 0 作成日時 2013/06/20 14:38:09 オブザベーションのバッファ長 48 更新日時 2013/06/20 14:38:09 削除済みオブザベーション数 0 保護 圧縮済み NO データセットタイプ ソート済み YES ラベル Fisher's Iris Data (1936) データ表現 WINDOWS_64 エンコード us-ascii ASCII (ANSI) エンジン/ホスト関連情報 データセットのページサイズ 65536 データセットのページ数 1 データページの先頭 1 ページごとの最大OBS数 1361 先頭ページのOBS数 150 データセットの修復数 0 ExtendObsCounter YES ファイル名 C:\Program Files\SASHome\SASFoundation\9.4\core\sashelp\iris.sas7bdat 作成したリリース 9.0401B0 作成したホスト X64_7PRO 作成順の変数 # 変数 タイプ 長さ ラベル 1 Species 文字 10 Iris Species 2 SepalLength 数値 8 Sepal Length (mm) 3 SepalWidth 数値 8 Sepal Width (mm) 4 PetalLength 数値 8 Petal Length (mm) 5 PetalWidth 数値 8 Petal Width (mm) ソート情報 ソート順 Species バリデート済み YES 文字セット ANSI
補足説明。
「options source2」は、読み込んだプログラムソースをログに出力するシステムオプション。
dataステップ内でのfileステートメントに一気にpathも含めてファイルを設定出来るが、どうせ後で読み込むのでfilenameステートメントで設定しておいた。
putステートメントの後に、+4などと書くことで適当にインデント設定して書き出し出来るが、ほぼ趣味である。
また、filenameステートメントで、ファイルのpathを記載する代わりに「TEMP」というキーワードでWORKライブラリ内に一時書き出しファイルを作成する事が出来る(#LNxxxxなどという名前でファイルの名前も自動設定される)が、ここでは敢えてしていない(しない方が便利な事もある)。
実際に使う場面。
無論、このサンプルは、単に「出来る!」というものでしかないが、dictionaryテーブルやcontentsプロシージャのデータセット出力と組み合わせる事で出来る事は増える。