03-22-2018 06:23 PM
I created a data dictionary with a column for field name and another column with the expected pattern (PRX) for each field. For example, the name fields allow letters, spaces, hyphens, commas, and apostrophes; so the pattern listed for those fields is /[A-Z\-\,\' ]/
I import the data dictionary then create macro variables to hold a listing of field names separated by space, and patterns separated by ~. However, when the code iterates through the patterns it chokes on the single quote. I've tried to put double quotes around the patterns in the data dictionary, and I tried putting ""&doubleQuotes"" around the macro variable, and tried %bquote, but I can't seem to find a combination that works. The SAS code and error message can be found below. The error message below corresponds to pattern /[A-Z\-\,\' ]/
ERROR: Closing delimiter "/" not found after regular expression "/[A-Z\-\,\".
ERROR: The regular expression passed to the function PRXMATCH contains a syntax error.
NOTE: Argument 1 to function PRXMATCH('/[A-Z\-\,\','L''ittle '[12 of 60 characters shown]) at
line 13 column 42 is invalid.
Any advice is appreciated.
proc sql noprint; select VARNAME, PATTERN into :varlist separated by ' ', :pattern separated by '~' from Ccbf_dd where PATTERN ne ''; quit; %let cntlist = &sqlobs; %put &varlist; %macro test(); %put %bquote(&pattern); %mend test; %test; %macro Val_check(); data QC_CCBF_values; set CCBF; length Issue_desc $250; Issue_desc=''; /* Initialize Issue_desc */ %do i = 1 %to &cntlist; /* iterate through the list of fields */ %let varname= %scan(%bquote(&varlist.), &i., %str(' ')); /* scans through the list of fields and assigns them one by one to the &varname macro var */ %let patternM= %scan(%bquote(&pattern.), &i., %str('~')); /* scans through the list of patterns and assigns them one by one to the &patternM macro var */ if &varname ne '' and prxmatch("&patternM",&varname.) eq 0 then Issue_desc=catx('; ',Issue_desc,"&varname"); %end; run; %mend Val_check; %Val_check();
03-23-2018 12:07 AM - edited 03-23-2018 12:08 AM
This works. Changes highlighted
%let varname= %scan(%bquote(&varlist.), &i., %str( )); %let patternM= %qscan(%bquote(&pattern), &i., ~);
03-23-2018 03:13 AM
Besides of the challenge with the single quote I believe that your current logic won't return the result you're after. The RegEx as per your code will only return something as invalid (value of zero) if ALL characters in the string are invalid.
03-23-2018 03:52 AM
03-23-2018 08:15 AM
Rather than messing round with tons of Klingon syntax (macro quoting), why not just single-quote the patterns from the start:
proc sql noprint; select VARNAME, quote(trim(PATTERN),"'") into :varlist separated by ' ', :pattern separated by '~' from Ccbf_dd where PATTERN ne ''; quit;
You can then change your PRXMATCH call to PRXMATCH(&PatternM,&Varname), and drop all the macro quoting. And you will not have to worry about patterns containing your string delimiter ("~", in this case), just use %sysfunc(Scan(&pattern,&i,~,Q)), instead of %SCAN or %QSCAN, then delimiters in patterns will not matter.
03-23-2018 10:28 AM - edited 03-23-2018 10:31 AM
This is for me one of these use cases where generating and including code is much easier to implement and debug than using macro code. People are of course different - but that's how my brain works.
Below some code which illustrates the approach.
data parameterTable; varname='varA'; pattern="/[^A-Z ,'-]/oi"; output; varname='VarB'; pattern="/[^xyz]/oi"; ;output; stop; run; filename codegen temp; data _null_; /* file print;*/ file codegen; set parameterTable; put @2 'if ' varname 'ne " " and prxmatch("' pattern +(-1)'",strip(' varname +(-1)')) > 0'; put @4 'then Issue_desc=catx("; ",Issue_desc,"' varname +(-1)'");'; run; data CCBF; varA='abc'; varB='xyz';output; varA='a1b'; varB='xyz';output; varA='abc'; varB='xbz';output; varA='a1b'; varB='xbz';output; stop; run; data QC_CCBF_values; set CCBF; length Issue_desc $250; Issue_desc=''; %include codegen / source2; run;
Besides of easily writing the generated code to the output window (file print) during development, I also like that it's easy to read in the SAS log when executed.
52 data QC_CCBF_values; 53 set CCBF; 54 length Issue_desc $250; 55 Issue_desc=''; 56 %include codegen / source2; NOTE: %INCLUDE (level 1) file CODEGEN is file C:\Users\ssapam\AppData\Local\Temp\SEG8912\SAS Temporary Files\_TD9428_SSAPAM_\#LN00019. 57 + if varA ne " " and prxmatch("/[^A-Z ,'-]/oi",strip(varA)) > 0 58 + then Issue_desc=catx("; ",Issue_desc,"varA"); 59 + if VarB ne " " and prxmatch("/[^xyz]/oi",strip(VarB)) > 0 60 + then Issue_desc=catx("; ",Issue_desc,"VarB"); NOTE: %INCLUDE (level 1) ending. 61 run;
Need further help from the community? Please ask a new question.