ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SAS macro 对两.sas文件进行程序code查重

SAS macro 对两.sas文件进行程序code查重 SAS macro 对两.sas文件进行程序code简单查重此macro用于对两个sas code文件进行程序code简单查重并输出.xlsx报告文件单元格背景色相似度等于100%的代码行为红色背景相似度大于等于95%且小于100%的代码行为橙色背景相似度大于等于90%且小于95%的代码行为黄色背景其他为白色背景SAS macro参数说明p_path product端程序所在路径或第一份sas code文件路径v_pathvalidation端程序所在路径或第二份sas code文件路径p_fileproduct端程序名或第一份sas code文件名v_filevalidation端程序名或第二份sas code文件名fencoding sas code文件的encodingstart_str_index 用于删除code中前导程序说明部分出现字符串start_str_index中赋值的字符串之前的code将不进行比对rate_gt 指定输出两SAS code相似度高于rate_gt值的codeoutputyn指定是否输出xlsx报告文件outpath指定输出xlsx报告文件的路径reportname指定输出xlsx报告文件的文件名不需要带扩展名debug 用于程序debug保留中间数据集/********************************************************* Author: Xinwei.zhong Create Date:2022-08-11 原创代码版权归本人Xinwei.zhong所有未经许可不可擅自挪用 *********************************************************/ %macro find_duplicates_pgm(p_path ,v_path ,p_file ,v_file ,fencoding ,start_str_index ,rate_gt ,outputyn ,outpath ,reportname ,debug); options nosource nosource2 nonotes; %put NOTE: -------------------- Macro[SYSMACRONAME.] Start --------------------; %if %symexist(_SASPROGRAMFILE) %then %let _fpath%qsysfunc(compress(_SASPROGRAMFILE,)); %else %let _fpath%sysget(SAS_EXECFILEPATH); %let program_path%sysfunc(prxchange(s/(.*)\\.*/\1/,-1,%upcase(_fpath.))); %let program_name%scan(_fpath., -2, .\); %put NOTE: ----[program_path program_path.]----; %put NOTE: ----[program_name program_name.]----; proc datasets libwork nolist memtypedata; delete rows comb_pv_pgm: __pgm_:; quit; %if %length(p_path.)0 %then %let p_path%str(program_path.); %if %length(v_path.)0 or %length(v_file.)0 or %length(p_file.)0 %then %do; %put ERR%str()OR: Parameter[v_path] or [v_file] or [p_file] uninitialized, please check!!; %return; %end; %if %sysfunc(fileexist(p_path.))0 %then %do; %put ERR%str()OR: Path[p_path p_path.] not exist, please check!!; %return; %end; %if %sysfunc(fileexist(p_path.\p_file.))0 %then %do; %put ERR%str()OR: File[p_path\p_file p_path.\p_file.] not exist, please check!!; %return; %end; %if %sysfunc(fileexist(v_path.))0 %then %do; %put ERR%str()OR: Path[v_path v_path.] not exist, please check!!; %return; %end; %if %sysfunc(fileexist(v_path.\v_file.))0 %then %do; %put ERR%str()OR: File[v_path\v_file v_path.\v_file.] not exist, please check!!; %return; %end; %if %length(fencoding.)0 %then %let fencoding%str(utf-8); %if %length(start_str_index.)0 %then %let start_str_index%str(###$##); %if %length(rate_gt.)0 %then %let rate_gt%str(0.88); %if %length(outputyn.)0 %then %let outputyn%str(Y); %let outputyn%upcase(outputyn.); %if %length(outpath.)0 %then %let outpath%str(p_path.); %if %sysfunc(fileexist(outpath.))0 %then %do; %put ERR%str()OR: Path[outpath outpath.] not exist, please check!!; %return; %end; %if %length(reportname.)0 %then %let reportname%str(find_duplicates_report); %if %length(debug.)0 %then %let debug 0; %macro read_deal_pgm(_path ,pgmname ,encoding ,startpgm , outdat); filename pgmfile _path.\pgmname. encodingencoding. lrecl8000; %let __start_p0; data outdat.1; infile pgmfile missover lengthlen endlastobs; input pgm $varying8000. len; n_n_; if index(upcase(pgm),%upcase(startpgm.)) then call symputx(__start_p,put(n,best.)); run; %PUT start_str_index [start_str_index.] __start_p __start_p.; data outdat.; set outdat.1(where(n__start_p. and not missing(pgm))); pgmstrip(tranwrd(tranwrd(tranwrd(lowcase(compbl(pgm)),09x, ),0ax, ),0dx, )); pgmprxchange(s/([^]{1,})//,-1,pgm); pgmprxchange(s/([^]{1,})//,-1,pgm); pgmprxchange(s/\/\*([^\/\*]{1,})\*\///,-1,pgm); pgmprxchange(s/\*([^;]{1,});//,-1,pgm); pgmprxchange(s/([\x80-\xFF][\x80-\xFF]([\x80-\xFF]*))//,-1,pgm); retain pgmcat 0; if strip(scan(pgm,1, )) in (data,proc) then pgmcat1; if strip(pgm) and kcompress(pgm,,ka); run; proc sort dataoutdat.; by pgmcat n; run; data rows; set outdat.(keeppgmcat n); by pgmcat n; retain start ; length row_info $20.; if first.pgmcat then startn; if last.pgmcat then do; if start^n then row_infostrip(vvalue(start))|| ~ ||strip(vvalue(n)); else row_infostrip(vvalue(n)); output; end; run; proc transpose dataoutdat. outoutdat. prefixcol; by pgmcat; var pgm; data outdat.; set outdat.; length pgm $20000.; pgmcatx( ,of col:); keep pgmcat pgm; /* if strip(pgm) not in (proc sort;,proc sort ;)*/ /* and kcompress(pgm) not in (data;run;);*/ run; %global _len; proc sql noprint; select max(length(strip(pgm))) into: _len trimmed from outdat.; quit; options varlenchk nowarn; data outdat.; length pgm $_len..; format pgm $_len..; informat pgm $_len..; merge outdat. rows(keeppgmcat row_info); by pgmcat; run; options varlenchk warn; %mend read_deal_pgm; %read_deal_pgm(_path%str(p_path.),pgmname%str(p_file.),encoding%str(fencoding.), startpgm%str(start_str_index.), outdat%str(__pgm_p)); %let lenp_len.; %read_deal_pgm(_path%str(v_path.),pgmname%str(v_file.),encoding%str(fencoding.), startpgm%str(start_str_index.), outdat%str(__pgm_v)); %let lenv_len.; %let minlen %sysfunc(min(lenp.,lenv.)); %let maxlen %sysfunc(max(lenp.,lenv.)); %put lenp lenp. lenv lenv.| minlen minlen. maxlen maxlen.; proc sql; create table comb_pv_pgm as select a.pgm as pgm_p,b.pgm as pgm_v, a.row_info as pgmrows_p,b.row_info as pgmrows_v from __pgm_p as a ,__pgm_v as b; quit; %if debug.0 %then %do; proc datasets nolist; delete rows __pgm_p __pgm_v __pgm_p2 __pgm_v2; quit; %end; data comb_pv_pgm; set comb_pv_pgm; length pgm_p1 $maxlen.. pgm_v1 $minlen..; if length(pgm_p)length(pgm_v) then do; pgm_p1pgm_p; pgm_v1pgm_v; end;else do; pgm_p1pgm_v; pgm_v1pgm_p; end; similar1-(complev(pgm_p,pgm_v)/(length(pgm_p)length(pgm_v))); if indexw(pgm_p1,pgm_v1, ;) then similar1; drop pgm_p pgm_v; rename pgm_p1pgm_p pgm_v1pgm_v; run; data comb_pv_pgm1; set comb_pv_pgm; simn0; cn(count(strip(translate(pgm_p, ,kcompress(pgm_p,,kp))), )1); do i1 to cn; if indexw(translate(pgm_v, ,kcompress(pgm_v,,kp)),strip(scan(strip(translate(pgm_p, ,kcompress(pgm_p,,kp))),i, )), ;) then simnsimn1; end; similar_indexwsimn/cn; if similar_indexwsimilar or (similar1 and length(pgm_p)(length(pgm_v)*3))then similarsimilar_indexw; if similarrate_gt.; length similarc $10.; similarcstrip(putn(similar*100,ifc(similar1,12.2,12.0))); %if debug.0 %then %do; drop cn simn similar_indexw pgm_p pgm_v i; %end; run; %macro get_pgm_rows(ori_pgmds,var,outds); proc sort datacomb_pv_pgm1(keepvar.) outoutds. nodupkey; by var.; run; data outds.; set outds.; if index(var.,~) then do; do ninput(scan(var.,1,~),best.) to input(scan(var.,2,~),best.); output; end; end;else do; ninput(var.,best.); output; end; run; proc sql undo_policynone; create table outds. as select a.var.,a.n,b.pgm from outds. as a left join ori_pgmds. as b on a.nb.n order by a.var.,a.n; quit; proc transpose dataoutds. outoutds. prefixcol; by var.; var pgm; data outds.; set outds.; length pgm $5000.; pgmcatx(0ax,of col:); keep var. pgm; run; proc sql noprint; select max(length(strip(pgm))) into: _len trimmed from outds.; quit; options varlenchk nowarn; data outds.; length pgm $_len..; format pgm $_len..; informat pgm $_len..; set outds.; run; options varlenchk warn; %mend get_pgm_rows; %get_pgm_rows(ori_pgmds__pgm_p1,varpgmrows_p,outds__pgm_rows_p); %get_pgm_rows(ori_pgmds__pgm_v1,varpgmrows_v,outds__pgm_rows_v); proc sql undo_policynone; create table _report_ds as select a.pgmrows_p,b.pgm as pgm_p,a.pgmrows_v,c.pgm as pgm_v,a.similarc,a.similar from Comb_pv_pgm1 as a left join __pgm_rows_p as b on a.pgmrows_pb.pgmrows_p left join __pgm_rows_v as c on a.pgmrows_vc.pgmrows_v order by a.pgmrows_p,a.pgmrows_v; select count(*) into: _chkn trimmed from _report_ds; quit; %if _chkn.0 and (outputyn.Y or outputyn.YES OR outputyn.1) %then %do; OPTIONS FORMCHAR|----||---|-/\*; ods _all_ close; title; footnote; ods excel fileoutpath.\reportname..xlsx styleexcel options(/*protect_worksheetyes*/ sheet_nameReport SHEET_INTERVALtable flow TABLES,ROWHEADERS,HEADERS,DATA,TEXT orientation landscape autofilterall Frozen_Headers on ABSOLUTE_COLUMN_WIDTH 15,15,90,90,15 suppress_bylinesyes center_horizontal yes EMBEDDED_TITLESon); proc report data_report_ds split $ nowd SPANROWS style(report) { protectspecialchars on just center CELLPADDING 0 CELLSPACING0} style(header) { protectspecialchars on just c Font_Size 9pt } style(column) { protectspecialchars on VerticalAlign Top Font_Size 9pt CELLPADDING 0 CELLSPACING0}; column (pgmrows_p pgmrows_v pgm_p pgm_v similarc similar); define pgmrows_p/Product Code$ Line Range order style(column)[VerticalAligncenter colorblack justleft width10 ex]; define pgmrows_v/Validation $Code Line$ Range style(column)[colorblack justleft width10 ex]; define pgm_p/Product Code order style(column)[colorblack justleft width100 ex height 3 ex]; define pgm_v/Validation Code style(column)[colorblack justleft width100 ex height 3 ex]; define similarc/Percentage of$ similarity style(column)[colorblack justleft width10 ex]; define similar/order noprint; compute similar; if similar1 then colorCXFF0000; else if 0.95similar1 then colorCXFF9900; else if 0.9similar0.95 then colorCXFFFF00; else colorCXFFFFFF; call define(_row_,style/merge,style[background||color||]); endcomp; quit; title; ods excel close; ods listing; %put ************************************************************************; %put * *; %put [ outpath.\reportname..xlsx ] has been created. ; %put * *; %put ************************************************************************; %end; %if _chkn.0 %then %do; %put ************************************************************************; %put **** [ No code with similarity greater than rate_gt. was found! ] ****; %put ************************************************************************; %end; %if debug.0 %then %do; proc datasets nolist; delete rows comb_pv_pgm: __pgm_:; quit; %end; %put NOTE: -------------------- Macro[SYSMACRONAME.] End --------------------; options source source2 notes; %mend find_duplicates_pgm;示例代码/*example*/ dm output;clear;log;clear;; proc delete data_all_; run; %let path%str(D:\zxw\SAS macro study\Find_Duplicates\data); %let _pgmfile_p%str(adrs.sas); %let _pgmfile_v%str(adrs1.sas); %find_duplicates_pgm(p_path%str(path.) ,v_path%str(path.) ,p_file%str(_pgmfile_p.) ,v_file%str(_pgmfile_v.) ,fencoding ,start_str_index%str(prepared by Xinwei.Zhong) ,rate_gt ,outpath ,reportname ,debug0);
返回列表