(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
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...
Huh?
You want to build a house without using wood, a hammer, nails or a saw?
Why?
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...
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
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.
/*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;
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;
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;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!
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.