BookmarkSubscribeRSS Feed
BrahmanandaRao
Lapis Lazuli | Level 10

I have a string like
a='a, b, cd, ef, gdj'
How to find 3rd comma

I want 3rd position  for above 

Data

17 REPLIES 17
tsap
Pyrite | Level 9
DATA WORK.HAVE;
	a='a, b, cd, ef, gdj';
	NEWVar=SCAN(a,3);
RUN;

Result:

a				NEWVar
a, b, cd, ef, gdj		cd

Hope this helps

noling
SAS Employee

This works if you want to know which position the 3rd comma is in. Stored in the third_loc var:

 

 

data temp(drop= i);
	a='a, b, cd, ef, gdj';
	do i = 1 to length(a);
		if substr(a,i,1)  = "," then comma_cnt+1;
		if comma_cnt=3 then do;
			third_loc=i;
			output;
			stop;
		end;
	end;
run;

Register today and join us virtually on June 16!
sasglobalforum.com | #SASGF

View now: on-demand content for SAS users

tsap
Pyrite | Level 9

If you were looking for the actual location of the literal third comma punctuation in the text and not the third value (delimited by the commas), you could also use this logic:

 

data WORK.Have;
	a='a, b, cd, ef, gdj';
 	call scan(a,4,pos,len,',');
  	pos=pos-1;
  	drop len;
run;

resulting output:

Obs 	a 			pos 
1 	a, b, cd, ef, gdj 	9 

Showing that the 3rd comma (',') was the 9th character in that text string

 

ref link to call scan: Sample 41355: Find the nth delimiter in a character string

noling
SAS Employee

This is a much better solution than mine. I user an &iterator in scan so much that I forget you can just say "give me the nth value"!


Register today and join us virtually on June 16!
sasglobalforum.com | #SASGF

View now: on-demand content for SAS users

ChrisNZ
Tourmaline | Level 20

Another way:

data _null_;
  A='a, b, cd, ef, gdjh';
  POS=length(prxchange('s/(([^,]*,){3}).*/\1/',1,A));
  put POS=;
run;

POS=9

 

This expression reads:

Find a group composed of:
(         start of group
([^,]*,)  anything-not-a-comma       repeated as required      then a comma   
                [^,]                          *                      ,

{3}       that combination (not comma then comma) appears thrice
)         end of group

.*        the group is followed by all remaining characters

\1        the second RegEx parameter asks that we only keep the group we matched
          i.e. we keep the three NotComma+Comma groups

Because we discard everything after the third comma, the length function gives us the position we want.

 

tsap
Pyrite | Level 9

Were any of the responses provided suitable as a solution to your problem? If so, please mark that post as the solution so that your post will close out as solved. Thanks.

hashman
Ammonite | Level 13

@BrahmanandaRao : 

I actually do like the CALL SCAN and regexen solutions better. But if you wanted to do it in a loop limited to 3 iterations, I can't help but suggest this:

data _null_ ;                    
  retain s 'a, b, cd, ef, gdjh' ;
  _s = s ;                       
  do i = 1 to 3 ;                
    pos = findc (_s, ",") ;      
    substr (_s, pos, 1) = "" ;   
  end ;                          
  put pos= ;                     
run ;                            

Kind regards

Paul D.

ScottBass
Rhodochrosite | Level 12

Yet another approach:

 

DATA WORK.HAVE;
   a='a, b, cd, ef, gdj';
   pos=0;
   do i=1 to 3;
   	pos=findw(a,',',pos+1,',','K');
   end;
   drop i;
RUN;

findw finds "words"

The 1st argument is the string to search.

The 2nd argument defines the "word" to find (a comma).

The 3rd argument defines the starting position for the search.  Needed to loop and find the 3rd comma.

The 4th argument defines the delimiters that separate words.  In this case the delimiter is also the word we're searching for.

The 5th argument "keeps" the delimiter, i.e. reverses the meaning.  A comma is now not treated as a delimiter.

 

Another approach (similar to hashman's but without the substr):

 

DATA WORK.HAVE;
   a='a, b, cd, ef, gdj';
   pos=0;
   do i=1 to 3;
   	pos=findc(a,',',pos+1);
   end;
   drop i;
RUN;

 

P.S.:  What are you really trying to do?  I doubt you want the position of the 3rd comma; instead, what do you want to do with that position? 


Please post your question as a self-contained data step in the form of "have" (source) and "want" (desired results).
I won't contribute to your post if I can't cut-and-paste your syntactically correct code into SAS.
hashman
Ammonite | Level 13

@ScottBass :

Neat! I like your FINDC approach better, but actually both are better than the SUBSTR pseudo-function known to be notoriously slow. 

 

ScottBass
Rhodochrosite | Level 12

@hashman wrote:

@ScottBass :

Neat! I like your FINDC approach better, but actually both are better than the SUBSTR pseudo-function known to be notoriously slow. 

 


Yeah, I like the FINDC approach better myself. 

 

I started with FINDW, mistakenly thought FINDC didn't have the start position parameter, hit the doc, then decided to post both approaches.

 

What would be nice is a parameter to "find the Nth occurrence" of [character|word] in FINDC | FINDW.  That's where @ChrisNZ 's solution is cool, but I doubt most folks would come up with that (but then Chris isn't "most folks" 😉 ).  I suspect the OP will have to hit the Perl Regex docs to understand that (really cool) solution.

 

 


Please post your question as a self-contained data step in the form of "have" (source) and "want" (desired results).
I won't contribute to your post if I can't cut-and-paste your syntactically correct code into SAS.
ChrisNZ
Tourmaline | Level 20

Ha @ScottBass! Bring on the compliments!

I just don't tire of them somehow! 😉

 

I feel like I have to add a few lines to explain the RegEx now.

hashman
Ammonite | Level 13

@ChrisNZ : But indeed.That would't hurt a bit.

hashman
Ammonite | Level 13

@ChrisNZ : Thanks 1e6!

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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.

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
  • 17 replies
  • 1632 views
  • 13 likes
  • 6 in conversation