Posted by hssnow in 分享 | 92 条评论
SAS中定义字符长度问题
前段时间翻看SASOR上的老帖子,在这个帖子中 ahuige 和 qkaiwei 讨论了下SAS中定义字符长度的问题,觉得挺有意思也挺有用处,摘录如下:
ahuige
1.第一个讨厌的特性,变量按第一次赋值决定变量的长度。
1 2 3 4 5 data xx; x='ab'; x='ab'||'c'; put x=; run;以上的语句,在log窗中可以看到,x的值依然是’ab’;这会让一个使用过其他语言写过这种天经地义的正确写法但又在sas中得到这种结果的人不知所措
ahuige
然后现在会有sas的卫道者跳出来说,这有什么,一个变量应该先定义长度,然后再赋值。下面的方法可以解决这个问题
1 2 3 4 5 6 data xx; length x$8.;*这里加一个定义长度; x='ab'; x='ab'||'c'; put x=; run;这个问题的确解决了,log窗里可以看到这里x=’abc’
好,现在初学者认为他已经了解了解决这个问题的方法。但是,下面的pitfall又来了。
1 2 3 4 5 6 data xx; length x$8; x='ab'; x='x||'c'; put x=; run;作者的本意是想得到x=’abc’,但是log里面又显示的是x=’ab’,作者还是又跳进陷阱了。
ahuige
卫道士又跳出来说,这个是因为sas自动给ab后面加上6个空格,
所以,应该再加一个trim函数.
1 2 3 4 5 6 data xx; length x$8.; x='ab'; x=trim(x)||'c'; put x=; run;上面的语句又解决问题了。log窗显示x=’abc’
好,后面的问题又来了。你说后面自动加空格,那你你长度当然就是固定的8了。看看我下面的语句
1 2 3 4 5 6 7 8 9 10 11 data xx; length x$8.; x='ab'; l=length(x); put x=; put l=; x=trim(x)||'c'; l=length(x); put x=; put l=; run;结果他的结果是第一个l表示长度为2,第二个l又表示长度为3.那空格为何又不算长度???
ahuige
卫道者又说,空格嘛,不算长度是应该的。
好,问题又来了。我试了试下面的语句
1 2 3 4 5 6 7 data xx; len1=length('x'); len2=length(' ____');*这里的4个_其实是空格;为了怕sasor网站把空格压缩了。 len2=length('_');*这里的1个_其实是空格;为了怕sasor网站把空格压缩了。 len3=length(''); put _all_; run;结果,不但’x’长度为1,4个空格长度为1,1个空格长度为1,连TMD空值长度都为1.我说怎么上次用判断一个字符的长度为零来判断是不是空值没得效,搞得我半死不活
上面有俩个len2可能是ahuige笔误,可能是len1,len2,len3,len4,如下:
1 2 3 4 5 6 7 | data xx; len1=length('x'); len2=length(' '); len3=length(' '); len4=length(''); put _all_; run; |
qkaiwei
1 SAS的字符变量默认的字符长度是8位,如果默认定义一个str=’ab’,str实际储存’ab____’,不足位空格补全,类似数据库中的定长型字段(char),当合并两个字符串时,str||str的实际结果是’ab____ab____’,看起来是’ab ab’。如果把这个结果赋值给一个字符变量x,而x变量没有用length改变默认长度,系统会将’ab____ab____’的前8位赋值给x,所以x 的值位’ab____’,看起来就是’ab’.
2 当计算非空字符串的长度时,首尾空格是被忽略的,全空字符串,SAS会将其看做一个空字符,至于length(”)的长度也为1,其实在SAS中”与”是一回事”=’ ‘,无论第二个空串中有几个空格。
ahuige
管理员啊。你的第一个段落我还是有一点点不认同,sas的默认长度可能在input时是8,但直接赋值是按第一次碰到的长度定义。比如我举的第一个例子
1 2 3 4 5 6 7 8 data xx; x='ab'; x='ab'||'c'; put x=; run; proc contents; run;////////////////以下是输出,可以看出length为2
# Variable Type Len Pos
1 x Char 2 0而且如果默认是8的话,x=’ab’||’c’没有理由不等于’abc’的。
其他几个例子就不说了嘛,你说得很清楚了。但这些与众不同的特性我想你没有理由说它们是优秀的吧?(比如第二段,想想,你将如何麻烦的去生成多个字符字段的一些有一点点变化的连接,其中的空格个数比较等控制更是讨厌)
qkaiwei
WO,对了,我忘了,我前几天还碰到这个问题。学艺不精啊!hihi,你以后叫我混混就是了。
你也别管它为什么,就像‘垃圾’为什么是‘土+立+土+及’,你想过没有?问过为什么没有?
原帖出处:
http://sasor.feoh.net/viewtopic.php?f=1&t=618&start=0
呵呵,有意思!!
昨天在人大上看到的一个帖子:
data _null_;
y=10600001;
z=substr(y,7,6);
put z=;
run;
所得结果:
z=600001
[回复]
hssnow 回复:
4月 19th, 2011 at 19:25
哈哈,刚搜了一下,nice,学习了啊
[回复]
哈哈,好古老的帖啊,多年前见过,还有印象的。
其实很多SAS初学者,特别是学过其他语言的,对SAS变量长度一经定义后不能被改变的规则表示不理解,实际中使用碰到出错,并且对此很愤慨。
其实每个语言有每个语言的一套,不可强求什么语言都是一样的规则,既然用到这门语言,那就按规则来玩。
[回复]
看了帖子的第二页,发现我也参与讨论了。
[回复]
hssnow 回复:
4月 19th, 2011 at 19:26
嘿嘿,前辈们当年可是各种给力啊
[回复]
不知道import中是否可以定义变量的长度,如下面语句:
PROC IMPORT OUT= WORK.Custer
DATAFILE= “C:\Documents and Settings\Administrator\桌面\Custmer_Views.csv”
DBMS=CSV REPLACE;
GETNAMES=YES;
DATAROW=2;
RUN;
我想定义变量的长度,不知道如何定义?
[回复]
hssnow 回复:
7月 13th, 2012 at 21:44
用import时好像是不行的,SAS是自动扫描数据行来决定变量的属性和长度的。
[回复]
今天就遇到这个问题了,excel导入的时候字符变量的值被截断了
[回复]