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.
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);
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.
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;
data want;
set have;
var2 = compress(var1,,'DK');
/*or*/
var3 = prxchange('s/.*____(\d+)@.*/$1/',1,var1);
run;
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;
Perhaps this isn't exceedingly ugly:
data want;
set have;
var2 = scan(substr(var1, index(var1, '____')), 1, '@');
run;
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.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.
Ready to level-up your skills? Choose your own adventure.