BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
112211
Obsidian | Level 7

(Without using SCAN function and do loops, PRXCHANGE)

data vjk;
Y='Hello doc,iam (name1) i have done my laboratory test is (dbp) and the result is (110)';output;
Y='Hello doc,iam (name2) i have done my laboratory test is (sbp) and the result is (120)';output;


Pick bracketed words and turn characters them to uppercase, create new variables mentioned like below
output
name       labtest  result
NAME1    WBC      110
NAME2   RBC        120

1 ACCEPTED SOLUTION

Accepted Solutions
Quentin
Super User

If it's just for fun, then one way to do it without SCAN or loops or regular expressions would be use just FINDC to find the parentheses, and substrn to get the text between the parentheses.  This uses the handy start-position of FINDC.

 

data have;
  infile cards truncover;
  input y $100. ;
cards4;
Hello doc,iam (name1) i have done my laboratory test is (dbp) and the result is (110)
Hello doc,iam (name2) i have done my laboratory test is (sbp) and the result is (120)
;;;;

data want ;
  set have ;
open1=findc(y,'(') ; close1=findc(y,')',open1) ; open2=findc(y,'(',close1) ; close2=findc(y,')',open2) ; open3=findc(y,'(',close2) ; close3=findc(y,')',open3) ; Name=upcase(substrn(y,open1+1,close1-open1-1)) ; Test=upcase(substrn(y,open2+1,close2-open2-1)) ; Result=upcase(substrn(y,open3+1,close3-open3-1)) ; put Name= Test= Result=; run ;

Of course it's wallpaper code that screams for looping over an array...

BASUG is hosting free webinars Next up: Don Henderson presenting on using hash functions (not hash tables!) to segment data on June 12. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.

View solution in original post

8 REPLIES 8
Tom
Super User Tom
Super User

Huh?

You want to build a house without using wood, a hammer, nails or a saw?

Why?

112211
Obsidian | Level 7
Its possible or not ,just I want to know.
Quentin
Super User

If it's just for fun, then one way to do it without SCAN or loops or regular expressions would be use just FINDC to find the parentheses, and substrn to get the text between the parentheses.  This uses the handy start-position of FINDC.

 

data have;
  infile cards truncover;
  input y $100. ;
cards4;
Hello doc,iam (name1) i have done my laboratory test is (dbp) and the result is (110)
Hello doc,iam (name2) i have done my laboratory test is (sbp) and the result is (120)
;;;;

data want ;
  set have ;
open1=findc(y,'(') ; close1=findc(y,')',open1) ; open2=findc(y,'(',close1) ; close2=findc(y,')',open2) ; open3=findc(y,'(',close2) ; close3=findc(y,')',open3) ; Name=upcase(substrn(y,open1+1,close1-open1-1)) ; Test=upcase(substrn(y,open2+1,close2-open2-1)) ; Result=upcase(substrn(y,open3+1,close3-open3-1)) ; put Name= Test= Result=; run ;

Of course it's wallpaper code that screams for looping over an array...

BASUG is hosting free webinars Next up: Don Henderson presenting on using hash functions (not hash tables!) to segment data on June 12. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.
Tom
Super User Tom
Super User

So let's see how many ideas we can come up with.

Here is one using CHAR() and SUBSTR() on the LEFT of the assignment statement.

 

data have;
  infile cards truncover;
  input y $100. ;
cards4;
Hello doc,iam (name1) i have done my laboratory test is (dbp) and the result is (110)
Hello doc,iam (name2) i have done my laboratory test is (sbp) and the result is (120)
;;;;

data want;
  set have ;
  array words $30 name test value;
  loc=1;
  do word=1 to 3 while(loc<length(y));
    do loc=loc to length(y) while ('(' ne char(y,loc));
    end;
    if char(y,loc)='(' then do i=1 to length(y)-loc until(')'=char(y,loc+i));
      if char(y,loc+i) ne ')' then substr(words[word],i,1)=upcase(char(y,loc+i));
    end;
    loc + i;
    drop word loc i;
  end;
run;

Result

 

Tom_0-1691080301215.png

 

ballardw
Super User

If all of your data looks like that with the desired values inside parentheses and in that order then SCAN is going to be a lot easier to write than PRX .

You don't mention whether result is supposed to be numeric or character as a result either.

No "loops" needed in this example: (assumes result should be numeric).

data want;
   set vjk;
   length name $ 25 labtest $ 10;
   name = scan(y,2,'()');
   labtest = scan(y,4,'()');
   result = input(scan(y,6,'()'),8.);
run;

Your PRX approach would basically be saying "get the first/second/third value inside ()". Scan does that with simpler syntax. If the ORDER of the values changes then provide a more realistic example.

Ksharp
Super User
/*It is more like a homework task.*/
data vjk;
Y='Hello doc,iam (name1) i have done my laboratory test is (dbp) and the result is (110)';output;
Y='Hello doc,iam (name2) i have done my laboratory test is (sbp) and the result is (120)';output;
run;

data want;
set vjk;
pid=prxparse('/\((\w+)\).*\((\w+)\).*\((\w+)\)/');
if prxmatch(pid,Y) then do;
 name=upcase(prxposn(pid,1,Y));
 labtest=upcase(prxposn(pid,2,Y));
 result=upcase(prxposn(pid,3,Y));
end;
drop pid;
run;
FreelanceReinh
Jade | Level 19

Another option is the "_infile_ trick" (see the 2018 thread "How to delimit large dataset ..." for a discussion):

data want(drop=y);
set vjk;
infile sasautos(verify.sas) dlm='()';
if _n_=1 then input @;
_infile_=y;
input @1 y name :$upcase40. y test :$upcase20. y result @@;
run;
Patrick
Opal | Level 21

Bit of a silly requirement but o.k. here you go.

data have;
  Y='Hello doc,iam (name1) i have done my laboratory test is (dbp) and the result is (110)';
  output;
  Y='Hello doc,iam (name2) i have done my laboratory test is (sbp) and the result is (120)';
  output;
  Y='Hello doc,iam (name2) i have done my laboratory test is (sbp)';
  output;
run;

data want(drop=_:);
  set have;
  length name labtest result $20;
  _s1=1;
  _s2=0;

  _s1=find(y,'(',_s1)+1;
  _s2=find(y,')',_s2+1);
  if _s2 then name=upcase(substr(y,_s1,_s2-_s1));

  _s1=find(y,'(',_s1)+1;
  _s2=find(y,')',_s2+1);
  if _s2 then labtest=upcase(substr(y,_s1,_s2-_s1));

  _s1=find(y,'(',_s1)+1;
  _s2=find(y,')',_s2+1);
  if _s2 then result=upcase(substr(y,_s1,_s2-_s1));
run;

proc print data=want;
run;

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
  • 8 replies
  • 1121 views
  • 9 likes
  • 7 in conversation