BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
rbetancourt
Obsidian | Level 7

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


1 ACCEPTED SOLUTION

Accepted Solutions
rbetancourt
Obsidian | Level 7

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

View solution in original post

4 REPLIES 4
Reeza
Super User

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. 

 

Spoiler
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

 

 

mkeintz
PROC Star

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.

 

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
rbetancourt
Obsidian | Level 7

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
Reeza
Super User
Why loop at all? Wouldn't a single call give you what you needed overall?

Also, not sure why you marked your own answer as correct, that's not usually how this works.

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 427 views
  • 0 likes
  • 3 in conversation