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

Hi,

 

I am trying to find out is there any way to achieve final output in a better way wherein I need to pull the middle value between first and last delimiter. For example: final = ABC -DEF -IJKL

 

data test1;
x='014-ABC -DEF -IJKL -20 NOV 2019';
run;

data test2;
set test1;
y = substr(x, 1, index(x, "-"));
yl = length(y)+1;
y6 = substr(x, yl);
y2 = scan(y6, -1, "-");
y2l = length(y2)+1;
y3l = length(y6)-y2l;
final = substr(x, yl, y3l);
run;

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
andreas_lds
Jade | Level 19

untested, using findc

data want;
   set test1;
   s = findc(x, '-');
   e = findc(x, '-', 'b');
   str = substr(x, s+1, e-s-1);
   
   drop s e;
run;

 

View solution in original post

5 REPLIES 5
Tom
Super User Tom
Super User

Here are two ways.  

One is to parse the string using - as delimiter and re-build the middle part using CATX().  Your messy string with inconsistent use of spaces in addition to hyphens between the words means the result is not exactly what was in the middle of the string.

Second is to use CALL SCAN() to find out where the second word starts and where the last word starts and then take the characters in between.

data test1;
  x='014-ABC -DEF -IJKL -20 NOV 2019';
  length middle1 middle2 $40 ;
  do index=2 to countw(x,'-')-1;
    middle1=catx('-',middle1,scan(x,index,'-'));
  end;
  call scan(x,2,start,len1,'-');
  call scan(x,-1,stop,len2,'-');
  middle2=substrn(x,len1+1,stop-start-1);
  put (_all_) (=/);
run;

Results

x=014-ABC -DEF -IJKL -20 NOV 2019
middle1=ABC-DEF-IJKL
middle2=ABC -DEF -IJKL
index=5
start=5
len1=4
stop=21
len2=11
andreas_lds
Jade | Level 19

untested, using findc

data want;
   set test1;
   s = findc(x, '-');
   e = findc(x, '-', 'b');
   str = substr(x, s+1, e-s-1);
   
   drop s e;
run;

 

FreelanceReinh
Jade | Level 19

Hi @1239,

 

Yet another option (more cryptic and probably slower, though) is the PRXCHANGE function:

data want;
set test1;
length final $30; /* specify a sufficient length */
final=ifc(countc(x,'-')>1, prxchange('s/^[^-]*-(.*)-[^-]*$/\1/',1,x), ' ');
run;

Explanation:

  • If two or more delimiters (here: hyphens) are found in variable X, the substring between the first and last delimiter -- zero or more arbitrary characters (except newline), denoted by .* -- is taken as the value of variable FINAL.
  • The substring between the beginning of the string (^) and the first hyphen as well as the substring between the last hyphen and the end of the string ($) -- both are sequences of arbitrary characters except the hyphen, denoted by [^-]* -- are not part of FINAL.
  • The replacement \1 stands for the substring matched by the pattern .* in parentheses. (See Tables of Perl Regular Expression (PRX) Metacharacters for the definitions.)
  • A single replacement (1 in the second argument of PRXCHANGE) achieves the desired result.
  • If less than two hyphens are found in X, FINAL is set to a missing value (third argument of the IFC function), but feel free to define FINAL differently in this case or to remove IFC and COUNTC entirely if the condition is not needed for your data.
1239
Calcite | Level 5

Hi, Thanks for your help. Your code also working but I couldn't explore more on PRXCHANGE function.

ChrisNZ
Tourmaline | Level 20

> explore more on PRXCHANGE function.

Like this?

data T;
  A=prxchange('s/[^-]+-(.*)-[^-]+/\1/', 1, 'A-B- C-D-E ');
run;

A = 'B- C-D'

 

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 1405 views
  • 3 likes
  • 5 in conversation