シングルコーテーション内のマクロ変数を展開する

下書きのまま、すっかりあげ忘れていた記事があったのでアップします。


今回の話は、マクロ変数の展開についてです。

さて今

%let M=いろは;

data Q;
 X='&M';
run;

といったコードを実行するとどうなるでしょうか?
やりたいこととしては、マクロ変数Mに「いろは」という値を入れて、それを後続のデータステップで
展開したいわけですが、この処理は期待どおりの結果になりません。







このように、マクロ変数が展開されません。
どうしてかというと、シングルコーテーションを使っているからです。
シングルコーテーション内のマクロ変数は展開されないというルールなんですね。
この場合は、ダブルコーテーションを使うのが正解でした。


さて、ここまではSASマクロを少しでも知っている人であれば、常識と言っていいことでしょう。

ただ、SASを長くやっていると、dmステートメント内の記述や、DDE等外部アプリケーションとの連携のため、シングルコーテーションを使う縛りがある上で、尚且つその中でマクロ変数を展開したいといったケースが生じることがあります。

無理。仕様だからしようがないといって諦めるのもそれはそれで一局の将棋ですが、新手一生の升田幸三はこう言いました。
「もう一歩突っこんで、不可能を可能にする努力、―将棋を創作し、また、勝負を勝ちきるには、この“えぐる”という修練が必要である」

というわけで、諦めずに、えぐってみましょう。

まず、思いつくのは

data E;
 X=%bquote('&M');
run;

ですね。シングルコーテーションに、マクロ変数展開を拒絶する能力があるというのならば、それを無効化して、意味のない記号文字に変えてしまえという発想です。
これをクォート処理っていいます。クォート処理を行う関数は山ほどあって、対象とする記号の種類や、処理のタイミングによって使い分けるのですが、詳しく書くと量がやばいことになるので、今回はしません。
%bquoteはシングルコーテーションもクォート対象なので今回使っています。
おまけですが%strは、デフォではシングルはクォート対象外ですが、
data E;
 X=%str(%'&M%');
run;
のように%を対象の前につけることで、同じ効果を得られます。

で、先ほどのコードを実行すると


となって、もれなくエラーになりました。
マクロ変数の展開はできているみたいですが、なぜでしょう?

わかりにくいんですが、ヒントはエラーメッセージです。

例えばですが、

data E;
X= $ABC$;
run;

というコードを実行すると、











あれ、同じメッセージだ!
どういうこと?

これはABCという文字列をくくっている$ドルマークに何の意味もないから、SASが、「お前が何をしたいのかさっぱりわからん、意味のある記号を使って、成立しているコードを書いてくれ」
っていう意味なんですね。


さて、これで先ほどの問題がわかりました。
data E;
 X=%bquote('&M');
run;

は確かに、シングルコーテーションのマクロ展開拒絶能力を無効化したことで、&Mの内容は展開できました。
しかし同時に、シングルコーテーションの、括った値を文字列として扱うという能力も無効化していたのです。
シングルコーテーションが全く意味のない役立たずの無意味文字になりさがったわけです。

なるほど、やっと解決法が見えてみました。

つまりマクロを展開する際は、シングルコーテーションを無効化(クォート)し、展開が終わったら再度有効化(クォート解除)すればいいわけです。

そこで、強制的にクォートを解除する関数%unquoteで

data A;
 X=%unquote(%bquote('&M'));
run;

とすれば






です。

ちなみに、残念ながらこれは別に僕が考えた新手ではなく、割と有名な定跡なんですけどね。


2 件のコメント:

  1. 先日は弊ブログをリンク申請いただき、有難うございました。
    リンクの件承知しました。こちらこそよろしくお願いいたします。
    併せてはてなブックマークに御ブログを追加しました。

    返信削除
  2. ありがとうございます!まったりツンデレ不定期日誌(旧まったりツンデレSASですよね?タイトル好きです)リンクに追加させていただきました!
    今後ともよろしくお願いいたします。

    返信削除