楼主: foocares
3554 7

[问答] 关于宏的嵌套和对应的字符函数 [推广有奖]

  • 0关注
  • 5粉丝

博士生

93%

还不是VIP/贵宾

-

威望
0
论坛币
548 个
通用积分
0
学术水平
28 点
热心指数
26 点
信用等级
24 点
经验
10891 点
帖子
299
精华
0
在线时间
158 小时
注册时间
2017-4-12
最后登录
2018-2-26

相似文件 换一批

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
求开解。
看到这一块时感觉好烦呀,困惑有如当年刚见识指针的指针一般。
好吧,我能理解,每个处理普通字符的宏函数都有一个对应处理特殊字符的宏函数,有如%UPCASE之于%QUPCASE。后者的作用就是能无视&和%这两个特殊解析宏的字符,看见&a不会去解析a, 而是直接当'&a'来处理。
但当书上这个例子一抛出,楼主便陷入了懵逼中。
%let a=begin;
%let b=%nrstr(&a);
%put UPCASE produces: %upcase(&b);
%put QUPCASE produces: %qupcase(&b);
嵌套的宏解析...
一点点来捋吧。首先,带%的函数一定是跟宏相关,要能解析括号里带&的宏字符参数,将宏替换为相应的值,再以对应的普通函数处理。所以这样理解的话,%UPCASE相当于专门处理宏参数的UPCASE函数。
在这个例子里,宏a对应的值解析为begin, 宏b的赋值因为无视&的存在,所以解析为&a。

那么,%UPCASE(&b)上来先对&b做解析,得到&a, 然后下一步呢?
是函数变成了UPCASE(&a), 还是UPCASE(begin)?
无论是哪个分支,都不大像能得出结果为小写的begin啊。
SAS运行结果如下:
1    %let a=begin;
2    %let b=%nrstr(&a);
3    %put UPCASE produces: %upcase(&b);
UPCASE produces: begin
4    %put QUPCASE produces: %qupcase(&b);
QUPCASE produces: &A


QUPCASE我大概能蒙对,因为不再对&a做进一步解析,所以会得出&A.
如果这里没搞懂,后头整个人都会不好了。因为下面还有一大坨%SUBSTR, %SCAN, %INDEX以及对应的特殊字符分身,可以想象这里头能埋伏多少变形海量题目来搞你,简直生无可恋。


顺带说一下,如果把代码从参数&b改为&a,去掉一层嵌套解析后,结果是这样的:
5    %let a=begin;
6    %let b=%nrstr(&a);
7    %put UPCASE produces: %upcase(&a);
UPCASE produces: BEGIN
8    %put QUPCASE produces: %qupcase(&a);
QUPCASE produces: BEGIN



二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:produces Produce upcase produc SUBSTR

回帖推荐

lava_mb 发表于8楼  查看完整内容

不好意思,最近事情较多,就少些长文吧……关于Macro Quoting的话题,论坛里有前辈已经总结分析的很好了,很透彻。我无法再锦上添花了,直接贴上链接,大家一起学习吧。 有关SAS中%nrstr()函数等macro quoting的问题 https://bbs.pinggu.org/thread-3591803-1-1.html 关于Macro Quoting https://bbs.pinggu.org/thread-3111084-1-1.html 另再推荐一篇论文,篇幅不长,但是解释的比较到位http://www.lexjansen.com/pharmasug ...
沙发
foocares 发表于 2017-5-3 11:40:28 |只看作者 |坛友微信交流群
自顶一下,求大神解惑。我把开关symbolgen开了,得到如下log:

199  options symbolgen;
200  %let a=begin;
201  %let b=%nrstr(&a);
202  %put UPCASE produces: %upcase(&b);
SYMBOLGEN:  Macro variable B resolves to &a
SYMBOLGEN:  Some characters in the above value which were subject to macro quoting have been
            unquoted for printing.
SYMBOLGEN:  Macro variable A resolves to begin
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这里为什么UPCASE不再对解析后的对象begin做进一步换成大写的操作?

UPCASE produces: begin
203  %put QUPCASE produces: %qupcase(&b);
SYMBOLGEN:  Macro variable B resolves to &a
SYMBOLGEN:  Some characters in the above value which were subject to macro quoting have been
            unquoted for printing.
QUPCASE produces: &A

使用道具

藤椅
foocares 发表于 2017-5-4 02:49:31 |只看作者 |坛友微信交流群
继续迷茫着,下一个例子:
%let a=one;
%let b=two;
%let c=%nrstr(&a &b)
%put C: &c
%put With SUBSTR: %substr(&c,1,2);
%put With QSUBSTR: %qsubstr(&c,1,2);
这里书上的道理我是懂的,第一个,先解析为
%substr(&a &b,1,2)
看上去要得到书上的结果one, 这里%substr是直接对字符串&a &b做一次解析取子字符串,所以从第一个字符开始读两位,得到&a, 这时候substr执行完,然后结果&a解析为one.

这里让人困惑的是,程序解析宏的顺序到底是怎么来的,为什么不是按substr(one two, 1,2)来?那就乱套了。

第二个,也是先得到qsubstr(&a &b, 1, 2), 然后取子字符&a出来,无视&停止下一步解析,得到结果&a.

好吧,道理我勉强懂,然而,机器上这段没能通过编译。。。
232  %put With SUBSTR: %substr(&c,1,2);
ERROR: Open code statement recursion detected.
233  %put With QSUBSTR: %qsubstr(&c,1,2);
ERROR: Open code statement recursion detected.

使用道具

板凳
foocares 发表于 2017-5-4 02:50:58 |只看作者 |坛友微信交流群
还有,为啥prep guide上还有%let a = &a这种用法?这不相当于把指针内容直接赋值给指针对象本身了么?这也行?

使用道具

报纸
foocares 发表于 2017-5-4 06:54:06 |只看作者 |坛友微信交流群
可怜被macro折磨的楼主啊,今天又使劲想了想,其实对结果的解释关键取决于函数执行的时序。
一步步细分来看:
%let b=%nrstr(&a);
对于%upcase(&b)的执行时序:
1. 因为&b含有macro trigger,所以先解析到&a
2. 这里谁先谁后很重要,在input stack里接下来一步如果是%upcase接管,
那么%upcase执行后结果变成了&A
3. 下一步,因为upcase已经执行过了,针对&A, word scanner不会再重复执行一遍转换大写的操作,结果只由macro trigger再行解析到begin, 这时候解析&a和&A没区别,都指向begin.

这里的关键在于,时序上要按照上头罗列的来,先解析第一步, 然后马上执行upcase操作,之后再解析upcase执行完之后的结果,这样按三步走才说的通.
那么换成QUPCASE执行的情况:
在第二步里同样是换成了&A, 但是因为mask掉了&,结果停留在&A不再做进一步解析.


同样道理来看:
%let a=one;
%let b=two;
%let c=%nrstr(&a &b);
310 The %INDEX Function  Chapter 9
%put C: &c
%put With SUBSTR: %substr(&c,1,2);

1. C会被解析为&a &b  (中间带空格)
1.1 但此时没有下一步解析! 这时候由函数substr接管!
2. substr马上接着执行, 取到子字符集为&a为函数执行结果
3. 因为结果里含macro trigger, SAS进一步解析结果为one.

而对于qsubstr,区别是取到子集&a后因为mask掉&, 所以结果停留在&a.

举一反三看%SCAN和%QSCAN:

%let a=one;
%let b=two;
%let c=%nrstr(&a*&b);
%put C: &c;
%put With SCAN: %scan(&c,1,*);
%put With QSCAN: %qscan(&c,1,*);

1. C先被解析为&a*&b (nrstr无视特殊字符,不trigger one和two的解析)
2. scan对&a*&b做扫描操作, 碰到分隔符*的第一个词的结果就是&a
3. 因为含macro trigger, SAS进一步解析&a为one

对于QSCAN, 在第二步扫描得到&a后mask掉&不触发下一步解析,最后结果为&a.

好吧,楼主暂时被自我催眠自我解释说通了,感觉好受一点。

使用道具

地板
NOVEMAND 发表于 2017-5-4 11:55:51 来自手机 |只看作者 |坛友微信交流群
foocares 发表于 2017-5-2 08:00
求开解。
看到这一块时感觉好烦呀,困惑有如当年刚见识指针的指针一般。
好吧,我能理解,每个处理普通字 ...
问楼主看的是那本书啊?我们(统计学)上课用的教材是黄燕的《统计分析与应用》里面好像没有涉及到宏

使用道具

7
foocares 发表于 2017-5-4 12:35:01 |只看作者 |坛友微信交流群
NOVEMAND 发表于 2017-5-4 11:55
问楼主看的是那本书啊?我们(统计学)上课用的教材是黄燕的《统计分析与应用》里面好像没有涉及到宏
你好,我看的是SAS官方的ADV准备指南。

使用道具

8
lava_mb 发表于 2017-5-8 23:16:10 |只看作者 |坛友微信交流群
foocares 发表于 2017-5-4 06:54
可怜被macro折磨的楼主啊,今天又使劲想了想,其实对结果的解释关键取决于函数执行的时序。
一步步细分来看 ...
不好意思,最近事情较多,就少些长文吧……关于Macro Quoting的话题,论坛里有前辈已经总结分析的很好了,很透彻。我无法再锦上添花了,直接贴上链接,大家一起学习吧。
有关SAS中%nrstr()函数等macro quoting的问题
https://bbs.pinggu.org/thread-3591803-1-1.html
关于Macro Quoting
https://bbs.pinggu.org/thread-3111084-1-1.html

另再推荐一篇论文,篇幅不长,但是解释的比较到位http://www.lexjansen.com/pharmasug-cn/2016/PS/PharmaSUG-China-2016-PS05.pdf
11.png
已有 1 人评分论坛币 学术水平 热心指数 信用等级 收起 理由
foocares + 5 + 1 + 1 + 1 精彩帖子

总评分: 论坛币 + 5  学术水平 + 1  热心指数 + 1  信用等级 + 1   查看全部评分

使用道具

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-26 12:57