为了弄清楚scan、%scan和%qscan使用,分情况试一试。通过试错进行学习。
在data步中使用scan、%scan和%qscan分别会出现什么情况。
/*课后活动信息*/
proc delete data = work._ALL_; quit;
/*case 1:data步*/
data _test;
length group $200.;
group="课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋";
proc print;
run;
![](https://img.haomeiwen.com/i18003060/d5b40824e536f14f.png)
- 试试第一种子情况。
如果想获得球类运动相关数据。
/*subcase1 分隔符为字符串,将scan分别替换为%scan、%qscan*/
data _test0;
set _test;
group1 = scan(scan(group, 2,"|"), 3,"\");
proc print;
run;
data _test1;
set _test;
group1 = %scan(%scan(group, 2,"|"), 3,"\");
proc print;
run;
data _test2;
set _test;
group1 = %qscan(%qscan(group, 2,"|"), 3,"\");
proc print;
run;
- 日志信息:
![](https://img.haomeiwen.com/i18003060/cfedd6a9aad1d386.png)
![](https://img.haomeiwen.com/i18003060/ab8f931f1aeced19.png)
- 输出结果:
使用scan有数据集输出;其他无正常输出。 -
print结果:
只有使用scan会有结果输出。
_test0
- 试试第二种子情况。
/*subcase2: 分隔符去掉引号,将scan分别替换为%scan、%qscan */
proc delete data = work._ALL_; quit;
dm ' log; clear; odsresult;clear; output; clear; ';
data _test;
length group $200.;
group="课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋";
proc print;
run;
data _test1_;
set _test;
group1 = %scan(%scan(group, 2,|), 3,\);
proc print;
run;
data _test2_;
set _test;
group1 = %qscan(%qscan(group, 2,|), 3,\);
proc print;
run;
- 日志信息:
scan第三个参数不加引号肯定报错,不予考虑;其他两种和1类子情况一样的报错 - 输出信息:
错误。 - print结果:
无。
- 试试第三种子情况。
/*subcase3:赋值宏变量,将scan分别替换为%scan、%qscan */
proc delete data = work._ALL_; quit;
dm ' log; clear; odsresult;clear; output; clear; ';
data _test;
length group $200.;
group="课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋";
proc print;
run;
%let pos2 = 2 ;
%let pos3 = 3 ; ;
%let hor = |;
%let slash = \;
%let group=课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋;
data _test0_;
set _test;
group1 = scan(scan(&group., %eval(&pos2.),&hor.),%eval(&pos3.),&slash.);
proc print;
run;
data _test1_;
set _test;
group1 = %scan(%scan(&group., %eval(&pos2.),&hor.), %eval(&pos3.),&slash.);
proc print;
run;
data _test2_;
set _test;
group1 = %qscan(%qscan(&group., %eval(&pos2.),&hor.), %eval(&pos3.) ,&slash.);
proc print;
run;
- 日志信息:
![](https://img.haomeiwen.com/i18003060/10d8946bc96d6c06.png)
-
输出信息:
错误 -
print结果:
错误 -
原因分析
![](https://img.haomeiwen.com/i18003060/7e3b0ba0488aff23.png)
宏变量赋值时使用scan、%scan和%qscan
- 试试第一种子情况。
/*subcase1 分隔符为字符串,将scan分别替换为%scan、%qscan*/
%let group1 = scan(scan("课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋", 2,'|' ), 3,'\');
%put &group1;
%let group2 = %scan(%scan("课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋", 2,'|' ), 3,'\');
%put &group2;
%let group3 = %qscan(%qscan("课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋", 2,'|' ), 3,'\');
%put &group3;
- 日志信息
![](https://img.haomeiwen.com/i18003060/b8364c8139751a2e.png)
2.1 情况:分隔符去掉引号。
/*subcase2.1 分隔符去掉引号,将scan分别替换为%scan、%qscan*/
%let group1 = scan(scan("课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋", 2,|), 3,\);
%put &group1;
%let group2 = %scan(%scan("课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋",2,|), 3,\);
%put &group2;
%let group3 = %qscan(%qscan("课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋", 2,|), 3,\);
%put &group3;
- 日志信息
![](https://img.haomeiwen.com/i18003060/3925e66f91416d6c.png)
2.2 情况:第一个参数引号移除
/*subcase2.1 引号都去掉,将scan分别替换为%scan、%qscan*/
%let group9 = scan(scan(课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋, 2,|), 3,\);
%put &group9;
%let group8 = %scan(%scan(课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋,2,|), 3,\);
%put &group8;
%let group7 = %qscan(%qscan(课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋, 2,|), 3,\);
%put &group7;
- 日志
![](https://img.haomeiwen.com/i18003060/bbbf54374552d740.png)
- 说明
scan:scan作为字符保留,而没有作为函数进行编译运行,这个等号后内容作为整体赋值;
%scan和%qscan作为宏函数发挥了作用,编译和运行,将所需要的值赋给了目标宏变量。
- 试试第三种子情况。
/*subcase3:赋值宏变量,将scan分别替换为%scan、%qscan */
%let pos2 = 2 ;
%let pos3 = 3 ; ;
%let hor = |;
%let slash = \;
%let group=课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋;
%let group1 = scan(scan(&group., %eval(&pos2.),&hor.),%eval(&pos3.),&slash.);
%put &group1;
%let group2 = %scan(%scan(&group., %eval(&pos2.),&hor.), %eval(&pos3.),&slash.);
%put &group2;
%let group3 = %qscan(%qscan(&group., %eval(&pos2.),&hor.), %eval(&pos3.) ,&slash.);
%put &group3;
- 日志信息
![](https://img.haomeiwen.com/i18003060/91dc2bc56d4dacf7.png)
- 说明
scan:提前赋值的宏变量进行了解析替换,但是scan作为字符保留,而没有作为函数进行编译运行;
%scan和%qscan均正确进行了替换,编译和运行,将所需要的值赋给了目标宏变量。
在宏中使用scan、%scan和%qscan
此处只讨论在宏里面的data步中的情况,主要看看宏中的data步中%scan和%qscan的情况。至于赋值问题,基础代码和宏代码中情况应该是一致的。
*取出球类运动相关数据;
data _test;
length group $200.;
group="课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋";
proc print;
run;
/*subcase1 分隔符为字符串,将scan分别替换为%scan、%qscan*/
data _test0;
set _test;
group1 = scan(scan(group, 2,"|"), 3,"\");
proc print;
run;
data _test1;
set _test;
group1 = %scan(%scan(group, 2,"|"), 3,"\");
proc print;
run;
data _test2;
set _test;
group1 = %qscan(%qscan(group, 2,"|"), 3,"\");
proc print;
run;
- 日志
![](https://img.haomeiwen.com/i18003060/db1e69087acdfe70.png)
-
说明
scan有正确的输出结果。 -
去掉第三个参数的引号
dm ' log; clear; odsresult;clear; output; clear; ';
%macro test();
*取出球类运动相关数据;
data _test;
length group $200.;
group="课外活动|书法绘画@硬笔书法@软笔书法@中国画@素描@油画\音乐@吉他@钢琴@竖笛@古筝@口琴\球类运动@乒乓球@羽毛球@篮球@足球@排球\棋类运动@围棋@中国象棋@国际象棋";
proc print;
run;
/*subcase1 引号去掉,将scan分别替换为%scan、%qscan*/
data _test0;
set _test;
group1 = scan(scan(group, 2,|), 3,\);
proc print;
run;
data _test1;
set _test;
group1 = %scan(%scan(group, 2,|), 3,\);
proc print;
run;
data _test2;
set _test;
group1 = %qscan(%qscan(group, 2,|), 3,\);
proc print;
run;
%mend;
%test();
- 日志
![](https://img.haomeiwen.com/i18003060/7bfb79e920549d65.png)
可见此种情况下,data步中scan适用,但是%scan和%qscan依然有报错并且和基础代码中报错一样。
总结
在data步中scan适用,在宏变量赋值时如果需要进行scan功能的函数运算,需要使用%scan和%qscan。
网友评论