BookmarkSubscribeRSS Feed
_Dan_
Quartz | Level 8

Hi,

 

I've got to tidy up our Calendars, and so I am reading in various bits of data. One of these is a simple 'ls' output from Unix of the PPM Calendar folder.

 

I've noticed on occasion that the same calendar will exist a few times, but there's a version number I can extract that'll tell me which Calendar is the most recently utilised. Here's an example of the 'ls' output. I have highlighted the bit I need in bold.

 

 

/opt/sas/platform/pm//work/calendar/CAL_END_AR______400@username
/opt/sas/platform/pm//work/calendar/CAL_END_AR______401@username
/opt/sas/platform/pm//work/calendar/CAL_END_AR______403@username
/opt/sas/platform/pm//work/calendar/CAL_END_AR______404@username

 

 

I'm trying to use SCAN to obtain the version number by first telling it to get the string after '_____', and the string before '@'.

 

x=scan(scan(Text,2,"_____"),1,"@");

SCAN is simply finding the first "_" rather than the concurrent "______". I've tried the 'o', 'm' and 'f' modifiers to no avail.

 

Maybe SCAN isn't appropriate here, but does anyone know how I go about getting the 400, 401, 403, 404 etc?

 

I know I could reverse the SCAN and find the '@' and then the '_____' but the principle remains - it'll only be finding the '_____' because it contains a single '_', so I am more interested in learning how to force SCAN to search for a consecutive delimiter, rather than haphazardly stumbling across a workaround.

7 REPLIES 7
andreas_lds
Jade | Level 19

Multiple consecutive delimiters are treated as one delimiter, so you need:

 

Version = scan(scan(Text, 4, '_'), 1, '@');

Depending on the paths you have, using a regular expression could yield more stable results. Assuming that the version consists of numbers only:

VersionRx = prxchange('s/.*_(\d+)@/$1/', 1, Text);
_Dan_
Quartz | Level 8

Thanks for your reply.

 

The first example, using SCAN with the assumption of 4 underscores won't work I'm afraid, as the strings are not always delimited with the same volume of underscores. Actual Calendar names have been changed, but the construct is the same.

 

/opt/sas/platform/pm/work/calendar/PART1_PART2_____331@username
/opt/sas/platform/pm/work/calendar/PART1_PART2_PART3_____332@username
/opt/sas/platform/pm/work/calendar/PART1_PART2_25_____333@username

I did come across the prxchange answer elsewhere, but I may as well just reverse the SCAN using the 'b' modifier to get what I want. What I'm interested in is a way to tell SCAN that it must search for a concurrent volume of delimiters rather than a single one, but I suspect that is never the intended purpose, as a delimiter is naturally a single character.

fdsaaaa
Obsidian | Level 7

using regular expressions would be my recommendation.  

But if you want SAS to find consecutive delimiters here is a highly inefficient method to do what you are asking for

DATA A;
B ='/opt/sas/platform/pm//work/calendar/CAL_END_AR______400@username';
DO I = 1 TO count(b,'_');
C =         SCAN(B,I,'_');
D =         SCAN(B,I,'_','M');
IF C NE D THEN DO;
  WANT=SCAN(C,1,'@');
  PUT WANT=;
  STOP;
END;
END;
RUN;

 

ed_sas_member
Meteorite | Level 14
data want;
	set have;
	var2 = compress(var1,,'DK');
	/*or*/
	var3 = prxchange('s/.*____(\d+)@.*/$1/',1,var1);
run;
ed_sas_member
Meteorite | Level 14
data have;
	input var1:$80.;
	datalines;
/opt/sas/platform/pm//work/calendar/CAL_END_AR______400@username
/opt/sas/platform/pm//work/calendar/CAL_END_AR______401@username
/opt/sas/platform/pm//work/calendar/CAL_END_AR______403@username
/opt/sas/platform/pm//work/calendar/CAL_END_AR______404@username
;
run;

data want;
	set have;
	var4 = scan(scan(tranwrd(var1,'______','*'),2,'*'),1,'@');
run;
Astounding
PROC Star

Perhaps this isn't exceedingly ugly:

 

data want;
   set have;
   var2 = scan(substr(var1, index(var1, '____')), 1, '@');
run;
Tom
Super User Tom
Super User

SCAN() uses ANY of the characters as a delimiter. So listing the same character one or ten times does not make a difference.

But it looks like you pattern could be parsed by SCAN() if you just search from the words from the end instead of the beginning.

x=scan(Text,-2,'@_');

Word number -1 will be username and word number -2 will by 400.

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 7 replies
  • 1504 views
  • 3 likes
  • 6 in conversation