SAS 程序冷知识——关于%quote系函数中%的转义问题

上一篇是关于%str和%nrstr两个函数的SAS 程序冷知识——一个关于%str和%nrstr的案例解读 - 简书

此处是上次的一个扩展。同样具有mask效果的quote一族是怎样处理%的呢?对于quote一族来说,%当然也具有两个功能,一个是宏的触发符号,一个是mask关键词的功能。

首先是bquote,这个函数的作用是mask所有特殊符号,所以在这函数里%不具备任何特殊符号的作用,所以不必用两个%mask。

有趣的是quote和nrquote,我们先看代码:

%let s1=%%@2个百分号;

%let s2=%%%%@4个百分号;

%let s3=%%%%%%%%@8个百分号;

%let s4=%%%%%%%%%%%%%%%%@16个百分号;

%macro a(quote=,nrquote=);

%put &=quote.;

%put &=nrquote.;

%mend;

%a(quote=%quote(&s1.),nrquote=%nrquote(&s1.));

%a(quote=%quote(&s2.),nrquote=%nrquote(&s2.));

%a(quote=%quote(&s3.),nrquote=%nrquote(&s3.));

%a(quote=%quote(&s4.),nrquote=%nrquote(&s4.));

结果是:

QUOTE=%@2个百分号

NRQUOTE=%@2个百分号

QUOTE=%@4个百分号

NRQUOTE=%%@4个百分号

QUOTE=%%@8个百分号

NRQUOTE=%%%%@8个百分号

QUOTE=%%%%@16个百分号

NRQUOTE=%%%%%%%%@16个百分号

我们发现对于nrquote来说,经过该函数%的个数都减半了。这个可以理解为:对于每对%而言,前一个%作为mask的符号,转义了后一个%的特殊作用,然后前一个%完成使命消失,从而最后的个数是原来的一半。

但是quote就有意思了,在4个百分号的时候,结果依然是一个%,并且按照后面的规则看,似乎quote在执行了第一遍转义之后,又进行了一次转义。

然后如果宏是这样的:

%macro b(quote=,nrquote=);

%put quote=%quote(&quote.);

%put nrquote=%nrquote(&nrquote.);

%mend;

%b(quote=&s1.,nrquote=&s1.);

%b(quote=&s2.,nrquote=&s2.);

%b(quote=&s3.,nrquote=&s3.);

%b(quote=&s4.,nrquote=&s4.);

结果就完全不一样,变得正常了。

quote=% 2个百分号

nrquote=% 2个百分号

quote=%% 4个百分号

nrquote=%% 4个百分号

quote=%%%% 8个百分号

nrquote=%%%% 8个百分号

quote=%%%%%%%% 16个百分号

nrquote=%%%%%%%% 16个百分号

这个结果表明,如果在宏变量赋值的时候,就带着函数quote,那么当使用的时候%会被作为转义符执行两次。为了验证这个结论我们再做一次试验。

%let s1=%quote(%%@2个百分号);

%let s2=%quote(%%%%@4个百分号);

%let s3=%quote(%%%%%%%%@8个百分号);

%let s4=%quote(%%%%%%%%%%%%%%%%@16个百分号);

%put quote=&s1.;

%put quote=&s2.;

%put quote=&s3.;

%put quote=&s4.;

其结果为:

quote=%@2个百分号

quote=%@4个百分号

quote=%%@8个百分号

quote=%%%%@16个百分号

这个结果基本验证了我们的想法。那么为什么quote就会执行两次呢?猜想原因是宏变量赋值的时候,是先执行宏函数,后赋值。我们以%let s3=%quote(%%%%%%%%@8个百分号);为例。当赋值的时候,s3的值可以%%%%@8个百分号。而当我们使用语句:%put quote=&s3.;的时候,由于解析宏变量中带有%quote的功能,所以在解析后再次执行转义功能,从而产生的结果”%%@8个百分号”。详见:SAS 程序冷知识——一个关于%str和%nrstr的案例解读(续) - 简书 

那么为什么nrquote就不会有问题呢?我们通过试验看到了quote的运行机制。quote和nrquote实际上本质是在字符的两端加上一个标志符号,这个符号往往我们无法直接通过put看到,但是如果用16进制解析就能清楚看到,我们显示示例如下:

%let s1=%%%%%%%%@8个百分号;

%let s2=%quote(%%%%%%%%@8个百分号);

%let s3=%nrquote(%%%%%%%%@8个百分号);

data _null_;

set sashelp.vmacro;

where name='S1';

S1=strip(value);

put S1= hex50.;

run;

data _null_;

set sashelp.vmacro;

where name='S2';

S2=strip(value);

put S2= hex50.;

run;

data _null_;

set sashelp.vmacro;

where name='S3';

S3=strip(value);

put S3= hex50.;

run;

执行之后可以看到

S1中25有8个,实际上是符号‘%’,到了S2中25变成了4个,这说明quote已经转义掉了其中的4个。但是S2的前后各多了一个符号,分别是03和08(20表示空格,是长度不够补位用的)。其他的位置,S1和S2完全一样,对应的就是文字“@8个百分号”。

到了S3就更有趣了,和S2内容一样,但区别在于开头的符号从03变成了05,然后百分号从25变成了10。

这样我们就大致理解quote和nrquote的操作了,当使用这个函数的时候,首先函数会在字符两端加上两个符号,结尾都是08,quote的开头是03,nrquote的开头是05。一旦套上的是05,SAS会进一步将原来的%和&转换成其他符号,来达到mask宏触发符号的目的。因此我们猜测执行顺序是这样的:

1、解析quote或nrquote中的宏变量。

2、两端加上mask符号08,03或05。

3、有%的话进行转义,将+,-等符号进行替换。

4、如果是nrquote,将%和&进行符号替换。

5、如果是quote,检查是否有%可以执行。

而之所以nrquote不会执行2次,是因为在第一次执行转义之后,所有的%就都被替换成其他字符了,因此也就不会又后面的转义了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容