ラベル マクロ関数: %NRBQUOTE の投稿を表示しています。 すべての投稿を表示
ラベル マクロ関数: %NRBQUOTE の投稿を表示しています。 すべての投稿を表示

2016年5月26日木曜日

マクロ言語入門6:クォート処理【%BQUOTE関数】




%STR と %BQUOTE は同じクォート処理系の関数ですが、まったく異なる動きをします。



%STR関数の性質

%STRで囲った範囲の特殊文字をクォートする。



%BQUOTE関数の性質

%BQUOTEで囲った範囲に「クォート処理されていないマクロやマクロ変数」が含まれる場合は可能な限り展開してから、結果に含まれる特殊文字をクォートする。




具体例


以下は、変数Aに値を入れるマクロです。

%macro TEST( VAL );

       data DT1;
           length A $30.;
           A = "&VAL";
       run;

%mend;


このマクロを実行して変数Aに「A,B,C」という値を入れたいとします。

 A 
 A,B,C  


まどろっこしい書き方ですが、以下のように書いて実行すると、、

%let X= A,B,C;
%TEST( &X );

ログ
ERROR: マクロに定義された数よりも多い定位置パラメータが与えられています。

エラーが出ます。これは 「%TEST( &X );」 → 「%TEST( A,B,C );」という順に展開されるわけですが、
「%TEST(A,B,C)」にはカンマが含まれてるので「3つ引数があるのか」と解釈されてしまうからです。




%BQUOTE関数を使ってみる


マクロ変数Xを展開した後の値「A,B,C」をクォート処理したいので、%BQUOTE関数を使います。

%let X = A,B,C;
%TEST( %bquote(&X) );

 A 
 A,B,C  




%BQUOTE , %NRBQUOTE関数


%BQUOTE と %NRBQUOTE は同じ性質ですが、クォート対象の文字が異なります。

マクロ関数対象の文字
%BQUOTE






+ - * / < > = ¬ ^ ~ ; , # 半角スペース
AND OR NOT EQ NE LE LT GE GT IN ' " ( )

以下のようにクォートする文字としてカッコを含めて記述すると、SASが混乱してバグってしまうので注意
%bquote(aa(bb)
%bquote(aa)bb)
%NRBQUOTE




%BQUOTE関数と同じ+ & %

このマクロ関数は挙動を勘違いしやすいうえ、扱いづらいため個人的にはあまり使ってません。
以下「%NRBQUOTEの詳しい挙動」も要確認!



💬 %NRBQUOTEの詳しい挙動

例えば、以下2つのマクロ変数があったとします。
  • マクロ変数X: 「&Y」という値がクォート処理されずに格納されている
  • マクロ変数Y: 「&Z」という値がクォート処理されずに格納されている


これに対して、以下を実行すると、、

%put %nrbquote(&X);

%BQUOTE, %NRBQUOTEで囲った範囲の「クォート処理されていないマクロやマクロ変数」は可能な限り展開されるので、

→「&X」を展開すると「&Y」
→「&Y」を展開すると「&Z」
→「&Z」というマクロ変数は存在しないため、これ以上展開できない
→「&Z」を展開できない旨のWARNINGをログに出力


%NRBQUOTEは「&」もクォート対象になっているので、

→「&Z」というマクロ変数として解釈されないようクォート処理




実践例


%SYSFUNC関数を使う時によくクォート処理します。詳細は以下過去記事をご覧ください。



とにかくマクロ関数は複雑で、何故そうなるの?という挙動が沢山あります。
実際に使用する際は、結果をよく確認したほうが良さそうです。


2015年9月16日水曜日

データステップ外で関数を使えるようにする「%SYSFUNC」その1




%SYSFUNCは、SAS関数やFCMPで定義した関数を、データステップ外で使えるようにしてくれます。
構文は簡単で、使用したい関数を%SYSFUNCで囲むだけ。



構文

%SYSFUNC(  関数  )




例


データステップ外でSUBSTR関数を使って文字の抽出を行い、ログに出力する例

%put %sysfunc( substr(ABCDE, 2, 3) );

---ログ---
BCD


%let MAC= ABCDE;
%put %sysfunc( substr(&MAC, 2, 3) );

---ログ---
BCD


ポイント
・全ての関数や関数の機能がサポートされてるわけではない。

・文字列を引用符(クオーテーション)で囲む必要がない。
例えば、データステップでは 「SUBSTR("ABCDE", 2, 3)」 というように文字列に引用符を付ける必要がありますが、上の例のように 「SUBSTR(ABCDE, 2, 3)」 と引用符は不要です。




落とし穴


以下の例はエラーが出てうまくいきません。

%let MAC= AB,CDE;
%put %sysfunc( substr(&MAC,2,3) );

ログ
ERROR: %SYSFUNC または %QSYSFUNC マクロ関数で参照されている関数 SUBSTR にある引数は多すぎます。


まず、マクロ変数MACが展開されると、、
%sysfunc( substr(&MAC,2,3) )

以下のようになります。
%sysfunc( substr(AB,CDE,2,3) )

この展開された文字にカンマが含まれてるのが問題で、
SUBSTR関数の中の第1引数が「AB」、第2引数が「CDE」、第3引数が「2」、第4引数が「3」と解釈されちゃってエラーが起きたわけです。



解決法


%BQUOTE関数などのマスク機能を持ったマクロ関数で囲んで、「AB,CDE」の中のカンマを無効化してあげます。

%let MAC= AB,CDE;
%put %sysfunc( substr(%bquote(&MAC),2,3) );

ログ
B,C

%BQUOTE関数ついては以下記事で解説しています
マクロ言語入門6:クォート処理【%BQUOTE関数】



その他注意

以下、データステップ100万回で取り上げられていますが、マクロ変数に結果をいれることで、誤差が出てしまうようなのでご注意下さい。

データステップ100万回 「マクロ変数に数値をいれて戻すと誤差がでちゃう場合がある問題について考える話」



その2につづく。。