Macros for SAS Application Developers
https://github.com/sasjs/core
mp_validatecol.sas
Go to the documentation of this file.
1 /**
2  @file
3  @brief Used to validate variables in a dataset
4  @details Useful when sanitising inputs, to ensure that they arrive with a
5  certain pattern.
6  Usage:
7 
8  data test;
9  infile datalines4 dsd;
10  input;
11  libds=_infile_;
12  %mp_validatecol(libds,LIBDS,is_libds)
13  datalines4;
14  some.libname
15  !lib.blah
16  %abort
17  definite.ok
18  not.ok!
19  nineletrs._
20  ;;;;
21  run;
22 
23  For more examples, see mp_validatecol.test.sas
24 
25  Tip - when contributing, use https://regex101.com to test the regex validity!
26 
27  @param [in] incol The column to be validated
28  @param [in] rule The rule to apply. Current rules:
29  @li ISINT - checks if the variable is an integer
30  @li ISNUM - checks if the variable is numeric
31  @li LIBDS - matches LIBREF.DATASET format
32  @li FORMAT - checks if the provided format is syntactically valid
33  @param [out] outcol The variable to create, with the results of the match
34 
35  <h4> SAS Macros </h4>
36  @li mf_getuniquename.sas
37 
38  <h4> Related Macros </h4>
39  @li mp_validatecol.test.sas
40 
41  @version 9.3
42 **/
43 
44 %macro mp_validatecol(incol,rule,outcol);
45 
46 /* tempcol is given a unique name with every invocation */
47 %local tempcol;
48 %let tempcol=%mf_getuniquename();
49 
50 %if &rule=ISINT %then %do;
51  &outcol=0;
52  if not missing(&incol) then do;
53  &tempcol=input(&incol,?? best32.);
54  if not missing(&tempcol) then if mod(&tempcol,1)=0 then &outcol=1;
55  end;
56  drop &tempcol;
57 %end;
58 %else %if &rule=ISNUM %then %do;
59  /*
60  credit SOREN LASSEN
61  https://sasmacro.blogspot.com/2009/06/welcome-isnum-macro.html
62  */
63  &tempcol=input(&incol,?? best32.);
64  if missing(&tempcol) then &outcol=0;
65  else &outcol=1;
66  drop &tempcol;
67 %end;
68 %else %if &rule=LIBDS %then %do;
69  /* match libref.dataset */
70  if _n_=1 then do;
71  retain &tempcol;
72  &tempcol=prxparse('/^[_a-z]\w{0,7}\.[_a-z]\w{0,31}$/i');
73  if missing(&tempcol) then do;
74  putlog 'ERR' +(-1) "OR: Invalid expression for LIBDS";
75  stop;
76  end;
77  drop &tempcol;
78  end;
79  if prxmatch(&tempcol, trim(&incol)) then &outcol=1;
80  else &outcol=0;
81 %end;
82 %else %if &rule=FORMAT %then %do;
83  /* match valid format - regex could probably be improved */
84  if _n_=1 then do;
85  retain &tempcol;
86  &tempcol=prxparse('/^[_a-z\$]\w{0,31}\.[0-9]*$/i');
87  if missing(&tempcol) then do;
88  putlog 'ERR' +(-1) "OR: Invalid expression for FORMAT";
89  stop;
90  end;
91  drop &tempcol;
92  end;
93  if prxmatch(&tempcol, trim(&incol)) then &outcol=1;
94  else &outcol=0;
95 %end;
96 
97 %mend mp_validatecol;