415 Views
April 05, 24
スライド概要
[第5回大阪SAS勉強会]小川良太
SAS言語を中心として,解析業務担当者・プログラマなのコミュニティを活性化したいです
How to Read Configuration Files with SAS 24-MAY-2019 Ryota Ogawa 1
⾃⼰紹介 ⼩川良太です 神⼾のTRIというところでデータマネージャーをしてい ます 主なお仕事:EDC、データクリーニング、SAS、 CDISC、Spot re、RPAなど 趣味:アニメ、ラノベ、電⼦マネー、ワークアウト 2
みなさん 想像してみてください 3.1
あなたはSASプログラマーです 3.2
あなたはSASプログラマーです 職場の上司から汎⽤的に利⽤できるSASプログラムを開 発するよう指⽰がありました 3.2
あなたはSASプログラマーです 職場の上司から汎⽤的に利⽤できるSASプログラムを開 発するよう指⽰がありました そのプログラムは全てのプロジェクトで使⽤するため、 プロジェクトごとに設定が必要です 3.2
あなたはSASプログラマーです 職場の上司から汎⽤的に利⽤できるSASプログラムを開 発するよう指⽰がありました そのプログラムは全てのプロジェクトで使⽤するため、 プロジェクトごとに設定が必要です 開発は社内のCSVポリシーにしたがい検証を⾏うため、 本番移⾏後のソースコード修正は変更対応となりとても めんどうです 3.2
あなたはSASプログラマーです 職場の上司から汎⽤的に利⽤できるSASプログラムを開 発するよう指⽰がありました そのプログラムは全てのプロジェクトで使⽤するため、 プロジェクトごとに設定が必要です 開発は社内のCSVポリシーにしたがい検証を⾏うため、 本番移⾏後のソースコード修正は変更対応となりとても めんどうです そこで設定はソースにハードコードしないで、設定ファ イルとして外出しすることにしました 3.2
ここで問題です 4.1
設定ファイルにはどんなフォーマッ トを使⽤しますか? 4.2
XML? example.xml(適当) 1 <breakfast_menu> 2 <food> 3 <name>Belgian Waffles</name> 4 <price>$5.95</price> 5 <description>Two of our famous Belgian Waffles with plenty of real maple syrup</ 6 <calories>650</calories> 7 </food> 8 <food> 9 <name>Strawberry Belgian Waffles</name> 10 <price>$7.95</price> 11 <description>Light Belgian waffles covered with strawberries and whipped cream</ 12 <calories>900</calories> 13 </food> 14 </breakfast_menu> 4.3
JSON? example.json(適当) 1 { 2 "menu": { 3 "id": "file", 4 "value": "File", 5 "popup": { 6 "menuitem": [ 7 {"value": "New", "onclick": "CreateNewDoc()"}, 8 {"value": "Open", "onclick": "OpenDoc()"}, 9 {"value": "Close", "onclick": "CloseDoc()"} 10 ] 11 } 12 } 13 } 4.4
YAML? example.yml(適当) 1 - martin: 2 name: Martin D'vloper 3 job: Developer 4 skills: 5 - python 6 - perl 7 - pascal 8 - tabitha: 9 name: Tabitha Bitumen 10 job: Developer 11 skills: 12 - lisp 13 - fortran 14 - erlang 4.5
プロパティファイル? example.properties(適当) 1 2 3 4 site=www.google.com name=DefaultAppName topic=Properties category=core-java 4.6
違う!! 4.7
Windowsなら〜 4.8
Windowsなら〜 INIファイルでしょ! 4.8
本⽇のお題 INIファイルをSASで読み込ん でみる 5
INIファイルとは? Windowsで使⽤されるテキストベースの設定ファイル パラメータは「キー」と「値」を持ち、等号で区切っ て定義する パラメータはセクションでグループ分けすることがで きる コメントの開始⽂字にはセミコロンを使⽤する 6.1
こんなファイルです(適当) example.ini 1 2 3 4 5 6 7 8 username = noha password = plain_text salt = NaCl [server_1] interface=eth0 ip=127.0.0.1 document_root=/var/www/example.org 6.2
INIファイルをSASで読み込ん でみる 7.1
INIファイルを準備します Setting.ini 7.2
Windows APIを呼び出すためのカタログファイルを作成します 1 2 3 4 5 6 7 8 9 10 11 12 13 14 filename SASCBTBL catalog "WORK.WIN32API.FUNCTION.SOURCE"; data _null_; input; file SASCBTBL; put _infile_; datalines4; routine GetPrivateProfileStringA module = KERNEL32 minarg = 6 maxarg = 6 stackpop = called returns = short ; 7.3
Windows APIを呼び出すためのカタログファイルを作成します (続き) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 arg 1 arg 2 arg 3 arg 4 arg 5 arg 6 ;;;; run; input input input output input input char char char char num char format format format format format format = = = = = = $cstr200.; $cstr200.; $cstr200.; $cstr200.; pib4.; $cstr200.; *lpAppName; *lpKeyName; *lpDefault; *lpReturnedString; *nSize; *lpFileName; libname OUT "C:\output"; proc copy in = WORK out = OUT memtype = catalog; select WIN32API; run; 7.4
MODULEN関数を使⽤して、Windows APIのGetPrivateProfileStringを呼び出 すマクロを定義 1 libname LIB "C:\output" access = readonly; 2 3 filename SASCBTBL catalog "LIB.WIN32API.FUNCTION.SOURCE"; 4 5 %macro ReadFromIniFile(AppName =, KeyName =, FileName =); 6 data TMP; 7 attrib SECTION length = $20; 8 attrib KEY length = $20; 9 attrib VALUE length = $200; 10 SECTION = "&AppName."; 11 KEY = "&KeyName."; 12 VALUE = ""; 13 rc = modulen ("GetPrivateProfileStringA", SECTION, KEY, "", VALUE, 14 200, "&FileName."); 15 run; 7.5
MODULEN関数を使⽤して、Windows APIのGetPrivateProfileStringを呼び出 すマクロを定義(続き) 1 proc datasets nolist; 2 append base = INI data = TMP; 3 delete TMP(memtype = data); 4 run; 5 quit; 6 %mend; 7.6
INIファイルの値をデータセット化して、マクロ変数に⼊ れます 1 2 3 4 5 6 7 8 9 10 %let iniFilePath = C:\output\Setting.ini; %ReadFromIniFile(FileName = &iniFilePath., %ReadFromIniFile(FileName = &iniFilePath., %ReadFromIniFile(FileName = &iniFilePath., %ReadFromIniFile(FileName = &iniFilePath., AppName AppName AppName AppName = = = = Setting, Setting, Setting, Setting, KeyName KeyName KeyName KeyName = = = = StudyId); InputPath); OutputPath); Debug); data _null_; set INI; call symputx(KEY, VALUE, "G"); run; 7.7
個⼈的なユースケース 8.1
試験名の定義 1 data AE; 2 set AE; 3 attrib STUDYID length = $10; 4 STUDYID = symget("StudyId"); 5 run; 8.2
フォルダパスの設定 1 libname IN v9 "&InputPath." access = readonly; 2 libname OUT v9 "&OutputPath." access = readonly; 8.3
デバッグモードの切り替え 1 data _null_; 2 /* */ 3 if symget("Debug") 4 call execute("options 5 end; 6 /* */ 7 else if symget("Debug") 8 call execute("options 9 end; 10 run; リリースモード デバッグモード = "0" then do; nomprint nomprintnest nomlogic nomlogicnest nosymbolgen;") = "1" then do; mprint mprintnest mlogic mlogicnest symbolgen;"); 本当はDOSUBLでしたかったけど、 システムオプションは動かなかった・・・ 8.4
補⾜ 9.1
MODULEN関数 外部ルーチンを呼び出し、数値を返します 構⽂ MODULEN(< control>, module, argument-1, argument-2 ..., argumentn) 引数 control コントロール⽂字列です(省略可能) module 使⽤する外部モジュールの名前を指定します argument-1, argument-2, ..., argument-n 要求されたルーチンに渡す引数を指定します 9.2
GetPrivateProfileString関数 INIファイル内の指定されたセクションから⽂字列を取得します 構⽂ DWORD GetPrivatePro leString( LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize, LPCTSTR lpFileName ); 引数 lpAppName キー名を含むセクションの名前 lpKeyName 関連付けられている⽂字列を取得するキーの名前 lpDefault デフォルトの⽂字列 lpReturnedString 取得した⽂字列を受け取るバッファへのポインタ nSize lpReturnedStringパラメーターが指すバッファーのサイズ(⽂字数) lpFileName INIファイルの名前 9.3
おしまい 10