DATA Step, Macro, Functions and more

PRX with a single quote

Accepted Solution Solved
Reply
Contributor
Posts: 43
Accepted Solution

PRX with a single quote

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.

 

Thanks,

Ryan

 

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();

 


Accepted Solutions
Solution
‎03-23-2018 11:15 AM
Esteemed Advisor
Posts: 5,474

Re: PRX with a single quote

Try using %qscan instead of %scan.

PG

View solution in original post


All Replies
Solution
‎03-23-2018 11:15 AM
Esteemed Advisor
Posts: 5,474

Re: PRX with a single quote

Try using %qscan instead of %scan.

PG
Contributor
Posts: 43

Re: PRX with a single quote

Thanks PGStats! That seems to have done the job. I appreciate your help.
PROC Star
Posts: 2,307

Re: PRX with a single quote

[ Edited ]

This works. Changes highlighted

%let varname= %scan(%bquote(&varlist.), &i., %str( ));  
%let patternM= %qscan(%bquote(&pattern), &i., ~);  

 

Respected Advisor
Posts: 4,665

Re: PRX with a single quote

@Ryanb2

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.

PROC Star
Posts: 2,307

Re: PRX with a single quote

Inded @Patrick is right.

 

If you want to "allow letters, spaces, hyphens, commas, and apostrophes" you probably want

 BADFLAG=prxmatch("/[^A-Z ,'-]/i", VAR);

Contributor
Posts: 43

Re: PRX with a single quote

You are absolutely right.  I didn't include the ^.  I so focusing on the single quote issue.  Thank you!

PROC Star
Posts: 249

Re: PRX with a single quote

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.

Respected Advisor
Posts: 4,665

Re: PRX with a single quote

[ Edited ]

@Ryanb2

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;
Contributor
Posts: 43

Re: PRX with a single quote

Thanks Patrick. I'll try this out sometime.
Contributor
Posts: 43

Re: PRX with a single quote

This appears to work as well. Thanks for the suggestion!
Contributor
Posts: 43

Re: PRX with a single quote

This works too.  Thanks for the suggestion!

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 11 replies
  • 188 views
  • 7 likes
  • 5 in conversation