## Return everything from the left of something

Solved
Frequent Contributor
Posts: 128

# Return everything from the left of something

[ Edited ]

Hi all,

I have this:

%let dsn=h1_1_final;

Data test;

Us=count("&dsn.","_");

Abv=scan("&dsn.",us,"_");

Run;

And i'm trying to end up with:

US=2

ABV=H1_1

However, the code above is giving me:

US=2

ABV=1

I can't figure out the right combination of scan or count and substr and length or whatever to get abv=h1_1

Any ideas?
Thanks

M

EDIT: This code will be part of a macro that cycles through 20+ different dataset names, some with 1 underscore, some with 2, etc.  So i need it to be dynamic.  Thanks

Accepted Solutions
Solution
‎05-16-2017 10:59 AM
Frequent Contributor
Posts: 118

## Re: Return everything from the left of something

If you want everything up to the last underscore, you can use CALL SCAN.

``````%let dsn=h1_1_final;

Data test(drop=position length);
Us=count("&dsn.","_");
call scan("&dsn.",us,position,length,"_");
abv=substr("&dsn.",1,position+length-1);
Run;

proc print data=test;
run;``````

All Replies
SAS Super FREQ
Posts: 817

## Re: Return everything from the left of something

Hi

You can also use DATA Step functions in the macro language by using %SYSFUNC. The SCAN function returns "words" deilmited by some chars. For your example, check the position of the last underscore and use the %SUBSTR function. the negative number in the FIND function will search from right to left.

``````%let dsn = h1_1_final;

%let last_us = %sysfunc( find(&dsn, _, -256) );

%let first_part = %substr(&dsn, 1, %eval(&last_us -1));

%put NOTE: &=dsn &=last_us &=first_part;``````
Posts: 3,167

## Re: Return everything from the left of something

[ Edited ]

For what it is worth, can also just be one-liner:

``````	   abv=prxchange('s/(^[^_]+_[^_]+)(_[^_]+\$|\s*\$)/\$1/', -1, "&dsn.");
``````

PROC Star
Posts: 8,163

## Re: Return everything from the left of something

Also, FWIW, can be a one liner with something like:

`abv=substr("&dsn.",1,findc("&dsn.","_",-999)-1);`

Art, CEO, AnalystFinder.com

Solution
‎05-16-2017 10:59 AM
Frequent Contributor
Posts: 118

## Re: Return everything from the left of something

If you want everything up to the last underscore, you can use CALL SCAN.

``````%let dsn=h1_1_final;

Data test(drop=position length);
Us=count("&dsn.","_");
call scan("&dsn.",us,position,length,"_");
abv=substr("&dsn.",1,position+length-1);
Run;

proc print data=test;
run;``````
Super User
Posts: 10,761

## Re: Return everything from the left of something

[ Edited ]

Very interesting question.

You only want the position of most right '_' ?

``````%let dsn=h1_1_final;
Data _null_;
Us=count("&dsn.","_");
Abv=substr("&dsn",1,findc("&dsn.","_",'b')-1);
put us= abv= ;
Run;``````

☑ This topic is solved.