Hi There,
In calling the ANYALNUM function in the second Data Step, I would expect the first 16 rows of output to assign 0 the val variable. Instead, I get 16. Is there something about the composition of the str variable or the DO loop I'm not seeing here? The subsequent calls to the ANYALNUM function returns exactly what I would expect.
This is 9.5M5 on Windows 10.
Appreciate any insights.
Best regards,
Randy
109 data string;
110 retain str;
111 length str $ 32767;
112 do i=32 to 126;
113 char = byte(i);
114 str = strip(cats(str, char));
115
116 end;
117 output;
118
119 run;
NOTE: The data set WORK.STRING has 1 observations and 3 variables.
NOTE: DATA statement used (Total process time):
real time 0.02 seconds
cpu time 0.01 seconds
120
121 data _null_;
122
123 set string;
124 put str;
125 do i=1 to length(str);
126 val = anyalnum(str, i);
127 sub_str = substr(str, i, 1);
NOTE: Variable "sub_str" was given a default length of 32767 as the result of a function call.
If you do not like this, please use a LENGTH statement to declare "sub_str".
128 put +4 sub_str= val=;
129 end;
130 run;
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
sub_str=! val=16
sub_str=" val=16
sub_str=# val=16
sub_str=$ val=16
sub_str=% val=16
sub_str=& val=16
sub_str=' val=16
sub_str=( val=16
sub_str=) val=16
sub_str=* val=16
sub_str=+ val=16
sub_str=, val=16
sub_str=- val=16
sub_str=. val=16
sub_str=/ val=16
sub_str=0 val=16
sub_str=1 val=17
sub_str=2 val=18
sub_str=3 val=19
sub_str=4 val=20
sub_str=5 val=21
sub_str=6 val=22
sub_str=7 val=23
sub_str=8 val=24
sub_str=9 val=25
sub_str=: val=33
sub_str=; val=33
sub_str=< val=33
sub_str== val=33
sub_str=> val=33
sub_str=? val=33
sub_str=@ val=33
sub_str=A val=33
sub_str=B val=34
sub_str=C val=35
sub_str=D val=36
sub_str=E val=37
sub_str=F val=38
sub_str=G val=39
sub_str=H val=40
sub_str=I val=41
sub_str=J val=42
sub_str=K val=43
sub_str=L val=44
sub_str=M val=45
sub_str=N val=46
sub_str=O val=47
sub_str=P val=48
sub_str=Q val=49
sub_str=R val=50
sub_str=S val=51
sub_str=T val=52
sub_str=U val=53
sub_str=V val=54
sub_str=W val=55
sub_str=X val=56
sub_str=Y val=57
sub_str=Z val=58
sub_str=[ val=65
sub_str=\ val=65
sub_str=] val=65
sub_str=^ val=65
sub_str=_ val=65
sub_str=` val=65
sub_str=a val=65
sub_str=b val=66
sub_str=c val=67
sub_str=d val=68
sub_str=e val=69
sub_str=f val=70
sub_str=g val=71
sub_str=h val=72
sub_str=i val=73
sub_str=j val=74
sub_str=k val=75
sub_str=l val=76
sub_str=m val=77
sub_str=n val=78
sub_str=o val=79
sub_str=p val=80
sub_str=q val=81
sub_str=r val=82
sub_str=s val=83
sub_str=t val=84
sub_str=u val=85
sub_str=v val=86
sub_str=w val=87
sub_str=x val=88
sub_str=y val=89
sub_str=z val=90
sub_str={ val=0
sub_str=| val=0
sub_str=} val=0
sub_str=~ val=0
NOTE: There were 1 observations read from the data set WORK.STRING.
NOTE: DATA statement used (Total process time):
real time 0.09 seconds
cpu time 0.09 seconds
131
132 data string2;
133 retain str2;
134 length str2 $ 32767;
135 do j = 32 to 47;
136 char2 = byte(j);
137 str2 = cats(str2, char2);
138 end;
139 output;
140
141 run;
NOTE: The data set WORK.STRING2 has 1 observations and 3 variables.
NOTE: DATA statement used (Total process time):
real time 0.02 seconds
cpu time 0.01 seconds
142
143 data _null_;
144
145 set string2;
146
147 do i=1 to length(str2);
148 val2 = anyalnum(str2, i);
149 sub_str2 = substr(str2, i, 1);
NOTE: Variable "sub_str2" was given a default length of 32767 as the result of a function call.
If you do not like this, please use a LENGTH statement to declare "sub_str2".
150 put +4 sub_str2= val2=;
151 end;
152 run;
sub_str2=! val2=0
sub_str2=" val2=0
sub_str2=# val2=0
sub_str2=$ val2=0
sub_str2=% val2=0
sub_str2=& val2=0
sub_str2=' val2=0
sub_str2=( val2=0
sub_str2=) val2=0
sub_str2=* val2=0
sub_str2=+ val2=0
sub_str2=, val2=0
sub_str2=- val2=0
sub_str2=. val2=0
sub_str2=/ val2=0
NOTE: There were 1 observations read from the data set WORK.STRING2.
NOTE: DATA statement used (Total process time):
real time 0.02 seconds
cpu time 0.01 seconds
153
154 data _null_;
155 test='?!@#$$%^&*()_+/Aa';
156 do k = length(test);
157 val3 = anyalnum(test, k);
158 sub_str3 = substr(test, k, 1);
159 put +4 sub_str3= val3=;
160 end;
161 run;
sub_str3=a val3=17
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
Thank you @Reeza and @mkeintz. Your responses are helpful. Mentally, I thought the second argument would 'walk-thru' a character at a time if this value were controled by a loop control variable. Combining the SUBSTR and ANYALNUM function together gives me what I am after--whether any character in the string is ALPHA or NUMERIC.
Best,
Randy
298 data _null_;
299
300 set string;
301 put str;
302 do i=1 to length(str);
303 sub_str = substr(str, i, 1);
NOTE: Variable "sub_str" was given a default length of 32767 as the result of a function call.
If you do not like this, please use a LENGTH statement to declare "sub_str".
304 val = anyalnum(sub_str);
305 put +4 sub_str= val=;
306 end;
307 run;
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
sub_str=! val=0
sub_str=" val=0
sub_str=# val=0
sub_str=$ val=0
sub_str=% val=0
sub_str=& val=0
sub_str=' val=0
sub_str=( val=0
sub_str=) val=0
sub_str=* val=0
sub_str=+ val=0
sub_str=, val=0
sub_str=- val=0
sub_str=. val=0
sub_str=/ val=0
sub_str=0 val=1
sub_str=1 val=1
sub_str=2 val=1
sub_str=3 val=1
sub_str=4 val=1
sub_str=5 val=1
sub_str=6 val=1
sub_str=7 val=1
sub_str=8 val=1
sub_str=9 val=1
sub_str=: val=0
sub_str=; val=0
sub_str=< val=0
sub_str== val=0
sub_str=> val=0
sub_str=? val=0
sub_str=@ val=0
sub_str=A val=1
sub_str=B val=1
sub_str=C val=1
sub_str=D val=1
sub_str=E val=1
sub_str=F val=1
sub_str=G val=1
sub_str=H val=1
sub_str=I val=1
sub_str=J val=1
sub_str=K val=1
sub_str=L val=1
sub_str=M val=1
sub_str=N val=1
sub_str=O val=1
sub_str=P val=1
sub_str=Q val=1
sub_str=R val=1
sub_str=S val=1
sub_str=T val=1
sub_str=U val=1
sub_str=V val=1
sub_str=W val=1
sub_str=X val=1
sub_str=Y val=1
sub_str=Z val=1
sub_str=[ val=0
sub_str=\ val=0
sub_str=] val=0
sub_str=^ val=0
sub_str=_ val=0
sub_str=` val=0
sub_str=a val=1
sub_str=b val=1
sub_str=c val=1
sub_str=d val=1
sub_str=e val=1
sub_str=f val=1
sub_str=g val=1
sub_str=h val=1
sub_str=i val=1
sub_str=j val=1
sub_str=k val=1
sub_str=l val=1
sub_str=m val=1
sub_str=n val=1
sub_str=o val=1
sub_str=p val=1
sub_str=q val=1
sub_str=r val=1
sub_str=s val=1
sub_str=t val=1
sub_str=u val=1
sub_str=v val=1
sub_str=w val=1
sub_str=x val=1
sub_str=y val=1
sub_str=z val=1
sub_str={ val=0
sub_str=| val=0
sub_str=} val=0
sub_str=~ val=0
Is the string data set as you expect? The output is a single row of a variable which is as follows from your code. Your VAL() function is referring to this string each time.
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
The second parameter tells SAS where to start searching but the count is still from the start, so the first alpha numeric character is at 16 until your index is over 16. It does not tell SAS to check just the character of interest.
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
The documentation for the anyalnum function says that the second argument
... specifies the position at which the search should start ...
So if the search starts at, say, position 2, the relative position of the "0" may be 15, but anyalnum apparently corrects for the starting position.
Thank you @Reeza and @mkeintz. Your responses are helpful. Mentally, I thought the second argument would 'walk-thru' a character at a time if this value were controled by a loop control variable. Combining the SUBSTR and ANYALNUM function together gives me what I am after--whether any character in the string is ALPHA or NUMERIC.
Best,
Randy
298 data _null_;
299
300 set string;
301 put str;
302 do i=1 to length(str);
303 sub_str = substr(str, i, 1);
NOTE: Variable "sub_str" was given a default length of 32767 as the result of a function call.
If you do not like this, please use a LENGTH statement to declare "sub_str".
304 val = anyalnum(sub_str);
305 put +4 sub_str= val=;
306 end;
307 run;
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
sub_str=! val=0
sub_str=" val=0
sub_str=# val=0
sub_str=$ val=0
sub_str=% val=0
sub_str=& val=0
sub_str=' val=0
sub_str=( val=0
sub_str=) val=0
sub_str=* val=0
sub_str=+ val=0
sub_str=, val=0
sub_str=- val=0
sub_str=. val=0
sub_str=/ val=0
sub_str=0 val=1
sub_str=1 val=1
sub_str=2 val=1
sub_str=3 val=1
sub_str=4 val=1
sub_str=5 val=1
sub_str=6 val=1
sub_str=7 val=1
sub_str=8 val=1
sub_str=9 val=1
sub_str=: val=0
sub_str=; val=0
sub_str=< val=0
sub_str== val=0
sub_str=> val=0
sub_str=? val=0
sub_str=@ val=0
sub_str=A val=1
sub_str=B val=1
sub_str=C val=1
sub_str=D val=1
sub_str=E val=1
sub_str=F val=1
sub_str=G val=1
sub_str=H val=1
sub_str=I val=1
sub_str=J val=1
sub_str=K val=1
sub_str=L val=1
sub_str=M val=1
sub_str=N val=1
sub_str=O val=1
sub_str=P val=1
sub_str=Q val=1
sub_str=R val=1
sub_str=S val=1
sub_str=T val=1
sub_str=U val=1
sub_str=V val=1
sub_str=W val=1
sub_str=X val=1
sub_str=Y val=1
sub_str=Z val=1
sub_str=[ val=0
sub_str=\ val=0
sub_str=] val=0
sub_str=^ val=0
sub_str=_ val=0
sub_str=` val=0
sub_str=a val=1
sub_str=b val=1
sub_str=c val=1
sub_str=d val=1
sub_str=e val=1
sub_str=f val=1
sub_str=g val=1
sub_str=h val=1
sub_str=i val=1
sub_str=j val=1
sub_str=k val=1
sub_str=l val=1
sub_str=m val=1
sub_str=n val=1
sub_str=o val=1
sub_str=p val=1
sub_str=q val=1
sub_str=r val=1
sub_str=s val=1
sub_str=t val=1
sub_str=u val=1
sub_str=v val=1
sub_str=w val=1
sub_str=x val=1
sub_str=y val=1
sub_str=z val=1
sub_str={ val=0
sub_str=| val=0
sub_str=} val=0
sub_str=~ val=0
Available on demand!
Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.