BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
alepage
Barite | Level 11

Hello,

 

How to find the position of each backlash and dot in:

 

DATA new_dataset;
INPUT text :$100.;
DATALINES;
/dwh_actuariat/sasdata/sas1999/nx/ingnovex.rd016y.prm.jun1999.dat.Z
;
RUN;
1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

@alepage wrote:
Your script works very well. Could you please provide me documentation on scan function with p, l, m. Also, what's the purpose of the call. where does go the information? Can we replace the call by a macro variable like %let fifth=scan(text,5,p,l,'/','m');

CALL SCAN() is what SAS calls a ROUTINE rather than a FUNCTION.  The CALL routines are documented with the other functions.  Look under C in the alphabetical lists.  The main difference is that a call routine can modifier the values of variables used as arguments.  That let's them return more than just a single value, like a function does.

 

You can put any text you want into a macro variable.  And then expand the macro variable wherever you want that text to become part of your code.  So if you made a macro variable with that text:

%let fifth=scan(text,5,p,l,'/','m');

You could then use it to generate that part of the CALL SCAN routine call in some later data step.

data ....
call &fifth;
...

But that just seems silly.

 

If you wanted the actually execute the CALL SCAN() routine in pure macro code you should look into using the %SYSCALL macro statement.

Example:

1    %let text=/dwh_actuariat/sasdata/sas1999/nx/ingnovex.rd016y.prm.jun1999.dat.Z;
2    %let start=0;
3    %let length=0;
4    %let n=5;
5    %let dlm=/;
6    %let modifiers=m;
7    %syscall scan(text,n,start,length,dlm,modifiers);
8    %let position=%eval(&start+&length);
9    %put &=start &=length &=position ;
START=32 LENGTH=2 POSITION=34

 

View solution in original post

9 REPLIES 9
Tom
Super User Tom
Super User

What did you try?  Did you try the INDEX() function? The FIND() function?  What about the CALL SCAN() method?

 

Why do you need to know?  What is the overall goal?  Perhaps you actually want the strings between the periods and slashes?  In that case look at the SCAN() function.

 

Note your example string has no backslashes.  Only regular slashes.

ballardw
Super User

What do you expect the output to look like?

 

Here is an example finding the position of slashes that writes to the log the character position in the string:

DATA new_dataset;
INPUT text :$100.;
numslash = countc(text,'/');

if numslash>0 then do;
   position=1;
   do i=1 to numslash;
   position= find(text,'/','i',position  );
   put position=;
   position=position+1;/* start searching for the next character starting in the next character from the one just found*/
   end;
end;
DATALINES;
/dwh_actuariat/sasdata/sas1999/nx/ingnovex.rd016y.prm.jun1999.dat.Z
;
RUN;

Finding periods would be basically the same but a different loop. Trying to search BOTH at the same time would be possible but likely more complicated code.

alepage
Barite | Level 11

Thanks for the SAS code. I was looking for a function that we could say, give me the position of the 5th backslash.

 

DATA new_dataset;
INPUT text :$100.;
numslash = countc(text,'/');

if numslash>0 then do;
   position=1;
   do i=1 to numslash;
   position= find(text,'/','i',position  );
   put position=;
   output;
   position=position+1;   /* start searching for the next character starting in the next character from the one just found*/
   end;
end;
DATALINES;
/dwh_actuariat/sasdata/sas1999/nx/ingnovex.rd016y.prm.jun1999.dat.Z
;
RUN;
Tom
Super User Tom
Super User

But Why??

 

If you want to extract the filename from the full specification just use SCAN() with -1 as the index.

data test;
  infile cards truncover;
  input fullname $200. ;
  filename = scan(fullname,-1,'/');
  path = substr(fullname,1,length(fullname)-length(filename));
DATALINES;
/dwh_actuariat/sasdata/sas1999/nx/ingnovex.rd016y.prm.jun1999.dat.Z
;

proc print;
run;

Result

Obs                                 fullname

 1     /dwh_actuariat/sasdata/sas1999/nx/ingnovex.rd016y.prm.jun1999.dat.Z

Obs                filename                                path

 1     ingnovex.rd016y.prm.jun1999.dat.Z    /dwh_actuariat/sasdata/sas1999/nx/

Note: Your example still does not have any backslashes, \ , only normal slashes, / .

ballardw
Super User

@alepage wrote:

Thanks for the SAS code. I was looking for a function that we could say, give me the position of the 5th backslash.


Still not stating what you want for output very clearly.

The code I used has a loop counter, that variable has the number of the backslash. So add and OUTPUT statement in the Loop and you will get an observation with the Position value and the value of that loop counter.

Note that your original request was ALL, and that is what I provided. 5th, if present, is just one of multiple.

 

So, I ask again, what do you expect the output data set to look like. Provide an example.

Ksharp
Super User
DATA _null_;
INPUT text :$100.;
call scan(text,5,p,l,'/','m');
position=p+l;
put 'The 5th / position is ' position ;
DATALINES;
/dwh_actuariat/sasdata/sas1999/nx/ingnovex.rd016y.prm.jun1999.dat.Z
;
RUN;
alepage
Barite | Level 11
Your script works very well. Could you please provide me documentation on scan function with p, l, m. Also, what's the purpose of the call. where does go the information? Can we replace the call by a macro variable like %let fifth=scan(text,5,p,l,'/','m');
Tom
Super User Tom
Super User

@alepage wrote:
Your script works very well. Could you please provide me documentation on scan function with p, l, m. Also, what's the purpose of the call. where does go the information? Can we replace the call by a macro variable like %let fifth=scan(text,5,p,l,'/','m');

CALL SCAN() is what SAS calls a ROUTINE rather than a FUNCTION.  The CALL routines are documented with the other functions.  Look under C in the alphabetical lists.  The main difference is that a call routine can modifier the values of variables used as arguments.  That let's them return more than just a single value, like a function does.

 

You can put any text you want into a macro variable.  And then expand the macro variable wherever you want that text to become part of your code.  So if you made a macro variable with that text:

%let fifth=scan(text,5,p,l,'/','m');

You could then use it to generate that part of the CALL SCAN routine call in some later data step.

data ....
call &fifth;
...

But that just seems silly.

 

If you wanted the actually execute the CALL SCAN() routine in pure macro code you should look into using the %SYSCALL macro statement.

Example:

1    %let text=/dwh_actuariat/sasdata/sas1999/nx/ingnovex.rd016y.prm.jun1999.dat.Z;
2    %let start=0;
3    %let length=0;
4    %let n=5;
5    %let dlm=/;
6    %let modifiers=m;
7    %syscall scan(text,n,start,length,dlm,modifiers);
8    %let position=%eval(&start+&length);
9    %put &=start &=length &=position ;
START=32 LENGTH=2 POSITION=34

 

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

SAS Enterprise Guide vs. SAS Studio

What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.

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
  • 9 replies
  • 649 views
  • 5 likes
  • 5 in conversation