由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
Statistics版 - 与Macro相关的字符函数
相关主题
greenhand asks a question on SAS Macro用SAS找单词
greenhand asks a question on SAS Macro靠,这个哪错了?
SAS macro variable resolution questionsas question!!!
大家说说这是电脑的错还是SAS的错如何用SAS找出含有特定字符的observation?
问个sas adv的问题为啥我的宏不被解释--SYMBOLGEN
Help: SAS codehow to create page x of y in SAS
求解SAS习题,谢谢sas macro 问题,
SAS macro DebugSAS help: 在 Macro 里循环调用 windows-display 的问题
相关话题的讨论汇总
话题: upcase话题: 解析话题: qupcase话题: begin话题: substr
进入Statistics版参与讨论
1 (共1页)
P*****i
发帖数: 63
1
看到这一块时感觉好烦呀,困惑有如当年刚见识指针的指针一般。
好吧,我能理解,每个处理普通字符的宏函数都有一个对应处理特殊字符的宏函数,有如%UPCASE之于%QUPCASE。后者的作用就是能无视&和%这两个特殊解析宏的字符。
但当书上这个例子一抛出,楼主便陷入了懵逼中。
%let a=begin;
%let b=%nrstr(&a);
%put UPCASE produces: %upcase(&b);
%put QUPCASE produces: %qupcase(&b);
嵌套的宏解析...
一点点来捋吧。首先,带%的func一定是跟宏相关,要能解析带&后面的字符串参数,将宏替换为相应的值,再以对应的普通函数处理。所以,%UPCASE 就是专门处理宏为参数的UPCASE函数。
在这个例子里,宏a对应的值解析为begin, 宏b的赋值因为无视&的存在,所以解析为&a。
那么,%UPCASE(&b)上来先对&b做解析,得到&a, 然后
下一步呢?
是函数表达式变成了UPCASE(&a), 还是UPCASE(begin)?
但无论是哪个分支,都不大像能得出结果小写的begin啊。
后面QUPCASE我大概能蒙对,因为不再对&a做进一步解析,所以会得出&A.
如果这里没搞懂,后头整个人都会不好了。因为下面还有一大坨%SUBSTR, %SCAN, %INDEX以及对应的特殊字符分身,可以想象这里头能埋伏多少变形的海量题目来搞你,简直生无可恋。
m******r
发帖数: 1033
2
这东西吧 确实烦人。 可也没什么大不了的。 无非就是上机自己试一试罢了,对着结
果怎么都能解释得通。 你也可以开那三个常用的option. 什么mprint symbolgen之类
,对着log一点点抠。 这就是sas的牛逼之处, 大不了对着log死磕,所有的问题都能
解决。 就凭这一点,一年给sas交一万块钱, 值。
P*****i
发帖数: 63
3
嗯,是哒,我就是在机器上跑过了还是不懂。
SAS运行结果如下:
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 produces: begin
~~~~~~~~~~~~~~~~~~~~~~~
这里为什么UPCASE不进一步执行替换大写的操作?
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
顺带说一下,如果把代码从参数&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
这个又反过来了,我不大理解后面这个结果,前头等于是先解析了宏a, 变为
UPCASE(begin)=BEGIN, 没问题;
但%QUPCASE(&a)不是该直接无视&, 按照普通字符串'&a'传给upcase作参数得到&A么?

【在 m******r 的大作中提到】
: 这东西吧 确实烦人。 可也没什么大不了的。 无非就是上机自己试一试罢了,对着结
: 果怎么都能解释得通。 你也可以开那三个常用的option. 什么mprint symbolgen之类
: ,对着log一点点抠。 这就是sas的牛逼之处, 大不了对着log死磕,所有的问题都能
: 解决。 就凭这一点,一年给sas交一万块钱, 值。

P*****i
发帖数: 63
4
下一个例子:
%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.
m******r
发帖数: 1033
5
我跟你说了,大可不必如此纠结。 宏这个东西虽然复杂,实际工作中只要简单试一试
,都能试出来。为什么我说不必纠结呢? 宏这个东西,在open code下跑和在 macro里
面跑,结果会不一样;还分编译阶段和执行阶段。 总之绕弯的地方很多 实际应用却很
少;宏编译器自己里面有时会解析好几次,有时解析一次 然后扔给数据步。 你把它当
个黑盒子用就行,好比一辆车能把你从A带到B, 你没必要非把它拆了 除非你以修车为
生。
你的代码我看了,头一个例子没什么解释不通的。 log不是已经有了一次大写的值嘛?
至于为什么最终结果没有大写,我觉着无所谓 (人家就解析一次 为什么要来来回回
在里面解析?)。 另外你知道sas对大小写不敏感吧 ?
你第二个例子,如果是你自己上机实验的,那挺好。 不通过就不通过,你哪里随便改
改,就能通过了,达到你的目的就行。 如果书上写能通过,你的却不能通过,那可能
要研究一下。
P*****i
发帖数: 63
6
感谢解答。
有空我可能还是搞清楚一下心里比较踏实,因为字符函数的应用场合是case sensitive
的,比如拿来做字符比较判断。
P*****i
发帖数: 63
7
还有,为啥还有%let a = &a这种用法?这不相当于把指针内容直接赋值给指针对象本
身了么?这也行?
m******r
发帖数: 1033
8
不知道你从哪里看的把宏和指针联系起来, 谁教你的啊?
sas 宏有一张宏变量的表。 宏运行的时候,解析其实就是查表
有这个概念 程序怎么写都无所谓。
P*****i
发帖数: 63
9
今天又想了下,结果取决于函数执行的时序。
一步步细分来看:
%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.

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

S*********e
发帖数: 21
10
天哪楼主我已经要看晕了…顺便问一下,你看prep guide的时候都会这样脑海里转换成
中文看吗?
m******r
发帖数: 1033
11
lz精神可嘉. 其实任何一种语言都有处理特殊字符的模块,不知道为什么sas特别加强
了这个功能。我想自有它的道理 我等无需杞人忧天
S******y
发帖数: 1123
12
用Python处理字符 非常简明
-StatsGuy
http://www.statsguy.net/

【在 m******r 的大作中提到】
: lz精神可嘉. 其实任何一种语言都有处理特殊字符的模块,不知道为什么sas特别加强
: 了这个功能。我想自有它的道理 我等无需杞人忧天

1 (共1页)
进入Statistics版参与讨论
相关主题
SAS help: 在 Macro 里循环调用 windows-display 的问题问个sas adv的问题
再请教advHelp: SAS code
请问SAS中如何删除字符变量内的零求解SAS习题,谢谢
菜鸟问题 (R & SAS)SAS macro Debug
greenhand asks a question on SAS Macro用SAS找单词
greenhand asks a question on SAS Macro靠,这个哪错了?
SAS macro variable resolution questionsas question!!!
大家说说这是电脑的错还是SAS的错如何用SAS找出含有特定字符的observation?
相关话题的讨论汇总
话题: upcase话题: 解析话题: qupcase话题: begin话题: substr