我輩はブロガーではない。ネタもまだない

SASとかDelphiあたりの人様の役に立たないネタを提供します

BaseSASユーザのためのGit(その4:sasプログラムの実行結果の管理)

夜な夜な真・女神転生Vをやっていて記事を全く更新していませんでした…。今4周目です(どうでもいい)


さて、皆さんはプログラムをどのように実行しているでしょうか。

  • SASを開き、プログラムを開いて実行
  • SASプログラムファイルを右クリックしてサブミット
  • SASプログラムファイルを右クリックしてバッチサブミット

通常は上記ののいずれかだと思いますが、この中で、バッチサブミットだけは少し結果が違うんですよね。
それは、「何も指定しなければログと結果はプログラムと同じフォルダに作成される」という点です。
(DMステートメントが使えない、というのもありますが)



お?「同じフォルダに出力される」ということは、SourceTreeの管理フォルダに作成される、つまり、Gitで管理できる、ということでもありますね!
早速試してみましょう。


まず、SubmitTestというブランチを切ります。

f:id:japelin:20211214112650p:plain
テストサブミット用のブランチ

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

f:id:japelin:20211214112030p:plain
右クリックメニューはカスタマイズできる

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

f:id:japelin:20211214112050p:plain
新規ファイル(?マーク)として、ログとリストファイルが表示されている

あれ?普通にサブミットするとHTMLの結果ファイルが生成されるはずなのに…


そうです、バッチサブミットだと、htmlではなく旧来のリストファイルが作成されるようになっています。
htmlを作成したい場合は、以下のようにods closeでlisting(リストファイル)への出力を止め、htmlの出力先を明示します。

ods _all_ close;
ods html path='C:\Users\FMVtest\Documents\Git\SAStest';

...中略

ods html close;

(普通、odsの出力先は必ず指定していると思いますが)


変更を保存して再度バッチサブミットしたところ、htmlファイルがプログラムと同じフォルダに作成されました。

f:id:japelin:20211214115809p:plain
リストファイルがなくなり、.htmが登録されている

 

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

f:id:japelin:20211214115840p:plain
メモ帳などで開くと、CharsetにShift-JISが設定されているのがわかる

これでは文字化けしてしまうので修正しましょう。
odsステートメントで、エンコーディングを指定するように修正します。

ods html path='C:\Users\FMVtest\Documents\Git\SAStest' encoding='utf-8';

再度バッチサブミットを実行して結果を確認します。

f:id:japelin:20211214115934p:plain
CharsetがShift-JISがutf-8に設定された

うんうん、ちゃんとutf-8になっていますね。


ログはどうでしょうか…

f:id:japelin:20211214120054p:plain
こちらもShift-JISなので文字化けしている

こちらも(見事に)文字化けしてます。

では、ログをutf-8に変更する方法はあるのでしょうか…


「proc printto log=」でログの出力先を変更できますが、これでは
ログの全体像が出てこないんですよね。
例えば、ログ先頭のサイト情報とか。

f:id:japelin:20211214122752p:plain
proc printo log=では、このあたりのログが出力されない


例えば、セッション自体をutf-8にしちゃえばリストもhtmlもログもutf-8になりますけど、当然、データセットやプログラムにも影響してしまうので、別の方法を採用します。


SASの起動時にconfigを読み込んでいることは、SASに詳しい方ならご存知かと思いますが、そこにオプションや実行プログラムを指定できるのはご存知でしょうか。


TERMSTMTシステムオプションを使用すると、以下のタイミングで指定したステートメントを実行できます。
https://documentation.sas.com/doc/ja/pgmsascdc/9.4_3.5/lesysoptsref/n0rjd82dx13qi7n1mw6rsljm7x1o.htm

  1. SAS起動(バッチ実行時)
  2. config読み込み
  3. initstmt
  4. -sysinで指定したプログラムの実行
  5. termstmt < ここ
  6. SAS終了


ですから、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"

を設定します。

f:id:japelin:20211214161902p:plain
パラメータに独自のCONFIGを指定する


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

f:id:japelin:20211214162255p:plain
CONFIGやオプションを変えて複数登録することも可能
f:id:japelin:20211214170116p:plain
コミットされていて、変更ファイルの一覧になければ、コミットしたHistoryからでもカスタム操作は可能


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

f:id:japelin:20211214162756p:plain
文字化け無し!

なお、temstmtは日本語が入らないのでShift-JISのままでも、utf-8でもどちらでも構いません。



最後に、残りのファイル

  • class.log
  • Mysasv9.cfg
  • sashtml.htm
  • termstmt.sas

もコミットしておきましょう。

f:id:japelin:20211214171159p:plain
コミットメッセージは分かりやすく