BaseSASユーザのためのGit(その4:sasプログラムの実行結果の管理)
夜な夜な真・女神転生Vをやっていて記事を全く更新していませんでした…。今4周目です(どうでもいい)
さて、皆さんはプログラムをどのように実行しているでしょうか。
通常は上記ののいずれかだと思いますが、この中で、バッチサブミットだけは少し結果が違うんですよね。
それは、「何も指定しなければログと結果はプログラムと同じフォルダに作成される」という点です。
(DMステートメントが使えない、というのもありますが)
お?「同じフォルダに出力される」ということは、SourceTreeの管理フォルダに作成される、つまり、Gitで管理できる、ということでもありますね!
早速試してみましょう。
まず、SubmitTestというブランチを切ります。

class.sasを右クリック→バッチサブミットします

結果ファイルである.lstとログファイル.logが生成されました。

あれ?普通にサブミットするとHTMLの結果ファイルが生成されるはずなのに…
そうです、バッチサブミットだと、htmlではなく旧来のリストファイルが作成されるようになっています。
htmlを作成したい場合は、以下のようにods closeでlisting(リストファイル)への出力を止め、htmlの出力先を明示します。
ods _all_ close; ods html path='C:\Users\FMVtest\Documents\Git\SAStest'; ...中略 ods html close;
(普通、odsの出力先は必ず指定していると思いますが)
変更を保存して再度バッチサブミットしたところ、htmlファイルがプログラムと同じフォルダに作成されました。

ちょっと待って下さい。htmlファイルを覗いてみると、エンコーディングが「Shift-JIS」になってます。

これでは文字化けしてしまうので修正しましょう。
odsステートメントで、エンコーディングを指定するように修正します。
ods html path='C:\Users\FMVtest\Documents\Git\SAStest' encoding='utf-8';
再度バッチサブミットを実行して結果を確認します。

うんうん、ちゃんとutf-8になっていますね。
ログはどうでしょうか…

こちらも(見事に)文字化けしてます。
では、ログをutf-8に変更する方法はあるのでしょうか…
「proc printto log=」でログの出力先を変更できますが、これでは
ログの全体像が出てこないんですよね。
例えば、ログ先頭のサイト情報とか。

例えば、セッション自体をutf-8にしちゃえばリストもhtmlもログもutf-8になりますけど、当然、データセットやプログラムにも影響してしまうので、別の方法を採用します。
SASの起動時にconfigを読み込んでいることは、SASに詳しい方ならご存知かと思いますが、そこにオプションや実行プログラムを指定できるのはご存知でしょうか。
TERMSTMTシステムオプションを使用すると、以下のタイミングで指定したステートメントを実行できます。
https://documentation.sas.com/doc/ja/pgmsascdc/9.4_3.5/lesysoptsref/n0rjd82dx13qi7n1mw6rsljm7x1o.htm
ですから、TERMSTMTを使って、SAS終了時にバッチ実行で生成されたログをutf-8に変換するコードを書けばいいのです。
それが以下のコード[termstmt.sas]です。
options noxwait xsync; %let ls=%eval(%sysfunc(getoption(LINESIZE))+1); %let xfile=%sysfunc(getoption(LOG)); %let yfile=%sysfunc(pathname(work))\_tmp_.log; %let zfile=%sysget(temp)\_mod_.log; filename y "&yfile"; filename z "&zfile" encoding='utf-8'; x "copy ""&xfile"" ""&yfile"""; data _null_; length logline $&ls. vl 8; infile y lrecl=&ls; input; file z; logline=_infile_; if logline="" then vl=0; else vl=length(logline); put logline $varying&ls.. vl; run; options noxsync; x "timeout /T 1 >nul & copy ""&zfile"" ""&xfile"" & del ""&zfile""";
詳しくは以前の記事バッチ実行ログから不要な改ページ行を削除するにまとまっていますが、流れと変更点をまとめておきます。
- 生成されたログを一時ファイルとして退避
- 退避したログをutf-8で書き換え
- 作成する一時ファイルはSASのテンポラリからtempに変更。
- 作成する一時ファイルのエンコーディングにutf-8を指定。
- timeoutコマンドを非表示にするため、コマンドに>nulを追加
- (DBCSだけ?)ラインサイズを超えて出力されるケースがあるため、ラインサイズに+1
このコードをclass.sasと同じフォルダに保存し、-TERMSTMTで実行させればいいのです。
(powershellでも変換できるようですが、別の理由があって、SASで実現させます)
ただし、右クリックのバッチサブミットでは標準のconfigが読み込まれるだけですし、そのconfigを変更するのも、右クリックメニューを変更するのも管理者権限が必要で、(既存の環境への影響という面で)リスキーです。
そのため、SourceTreeからバッチサブミットが実行できるように構成します。
まずは、専用のconfigファイルを作成します。
既存のsasv9.cfgをコピーして、最後にTERMSTMTシステムオプションを追加してもいいですが、以下のようなテキストファイルが簡単です。
これをMysasv9.cfgとして保存します。(エンコーディングはShift-JISにすること)
-CONFIG "C:\Program Files\SASHome2\SASFoundation\9.4\nls\ja\sasv9.cfg" -TERMSTMT=' %inc "termstmt.sas"; '
続いて、SourceTreeでカスタム操作を登録します。
ツール>オプション>カスタム操作>追加から、
- メニュー名:SASバッチ実行(任意)
- 別のウィンドウで開く:ON
- 実行するスクリプト:SASのフルパス
- パラメータ:-config "$REPO\Mysasv9.cfg" -sysin "$FILE"
を設定します。

登録が終わったら、class.sasを右クリックして、カスタム操作>SASバッチ実行を選択します。


結果、きちんとログがutf-8で生成されました。

なお、temstmtは日本語が入らないのでShift-JISのままでも、utf-8でもどちらでも構いません。
最後に、残りのファイル
- class.log
- Mysasv9.cfg
- sashtml.htm
- termstmt.sas
もコミットしておきましょう。
