簡體   English   中英

將等號傳遞給SAS中的宏

[英]Passing an equals sign to a macro in SAS

我試圖在數據步驟中生成代碼,然后將代碼傳遞到宏中,然后運行該代碼。 我知道這有點round回,但我想不出更好的解決方案,因為我的代碼內容基於數據集中的內容。

在我的數據集“ test2”中,我只有一個觀察到變量“ statement”,它等於

j1 =輸入(j,anydtdtm。); 放下j; 重命名j1 = j; k1 = input(k,anydtdtm。); 下降k; 重命名k1 = k; l1 = input(l,anydtdtm。); 降l; 重命名l1 = l;

我有一個基本上是一個宏

%macro dummy(ds,statements);
    data &ds.2;
        set &ds.;    
        &statements.
    run;
%mend;

然后我使用調用執行以下內容:

data test3;
    set test2;
    call execute('%dummy('||strip(ds)||','||strip(statement)||')');
run;

但是我收到以下錯誤:

ERROR: The keyword parameter J1 was not defined with the macro.

顯然,SAS將我的“ =”符號解釋為宏變量內容以外的其他內容。 我嘗試使用%str並將呼叫執行更改為:

data test3;
    set test2;
    call execute('%dummy('||strip(ds)||','||%str(strip(statement))||')');
run;

但這沒用。 有人有想法么?

謝謝你的幫助!!

首先,如果使用命名參數,這不是問題。

%macro dummy(ds=,statements=);
    data &ds.2;
        set &ds.;    
        &statements.
    run;
%mend;


data class;
  set sashelp.class;
run;

data fixes;
  infile datalines truncover;
  length statement $40 all_statements $512 execstr $1024;
  do _n_ = 1 to 2;
      input @1 statement $40.;
      all_statements=catx(';',all_statements,statement);
  end;
  put all_statements;
  execstr = cats('%dummy(ds=class,statements=',all_statements,';)');
  call execute(execstr);
  datalines;
if sex='M' then m_height=height
if sex='F' then f_height=height
;;;;
run;

然后,SAS看到命名參數等號,並且知道從該參數到下一個逗號的所有內容都是該參數的值。

當然,如果您有逗號,您仍然需要做一些事情。 這是你親密無間的地方。 %str需要引用宏調用 ,而不是宏調用構造 -換句話說,它必須位於引號內。

data fixes;
  infile datalines truncover;
  length statement $40 all_statements $512 execstr $1024;
  do _n_ = 1 to 2;
      input @1 statement $40.;
      all_statements=catx(';',all_statements,statement);
  end;
  put all_statements;
  execstr = cats('%dummy(ds=class,statements=%nrstr(',all_statements,';))');
  call execute(execstr);
  datalines;
if sex in ('M','F') then mfheight=height
if sex='F' then f_height=height
;;;;
run;

我個人在這里喜歡%nrstr ,因為它還消除了可能具有某些含義的那些討厭的“&”號和百分號。

將其放在此處意味着SAS運行該調用execute時,它將傳遞該%str%nrstr並引用正在發送的值。

當您在其他地方擁有它時:

execstr = cats('%dummy(ds=class,statements=',%nrstr(all_statements),';)');

被保護/引用的不是all_statements內的文本,而是實際上的all_statements字符(換句話說, 變量名 )。 這實際上對您沒有多大作用。

傳遞等號很容易,只需在調用中使用命名參數即可。

%dummy(ds=x,statement=x=2)

它正在通過分號,這真的很難。 為此,您需要引用宏調用中的值。 您可以使用宏引用來做到這一點,但是我發現使用普通的引號並將其從宏代碼中刪除會更容易。

使用DEQUOTE()函數使宏刪除可能圍繞參數值的所有引號。

%macro dummy(ds,statements);
data &ds.2;
  set &ds.;    
  %sysfunc(dequote(&statements))
run;
%mend;

讓我們將示例語句設置為數據集。

data have;
  ds='x';
  statements=
   'j1=input(j,anydtdtm.); drop j; rename j1=j;'
|| 'k1=input(k,anydtdtm.); drop k; rename k1=k;'
|| 'l1=input(l,anydtdtm.); drop l; rename l1=l;'
  ;
run;

還有一些用於這些語句的示例數據。

data x;
 j='01JAN1960';
 k='10FEB2010';
 l='2014-05-01';
run;

現在,您可以使用數據集來生成呼叫。 使用QUOTE()函數將語句括在引號中。

options mprint;
data _null_;
  set have ;
  call execute(cats('%nrstr(%dummy)(',ds,',',quote(trim(statements)),')'));
run;

這是日志。

1    + %dummy(x,"j1=input(j,anydtdtm.); drop j; rename j1=j;k1=input(k,anydtdtm.); drop k; rename
k1=k;l1=input(l,anydtdtm.); drop l; rename l1=l;")
MPRINT(DUMMY):   data x2;
MPRINT(DUMMY):   set x;
MPRINT(DUMMY):   j1=input(j,anydtdtm.);
MPRINT(DUMMY):   drop j;
MPRINT(DUMMY):   rename j1=j;
MPRINT(DUMMY):  k1=input(k,anydtdtm.);
MPRINT(DUMMY):   drop k;
MPRINT(DUMMY):   rename k1=k;
MPRINT(DUMMY):  l1=input(l,anydtdtm.);
MPRINT(DUMMY):   drop l;
MPRINT(DUMMY):   rename l1=l;
MPRINT(DUMMY):   run;

在以下情況中,可能更容易在文件中生成代碼,然后使用%include語句提交代碼:

filename tempsas temp;
data test3;
  set test2;
  file tempsas;
  put
    'data ' ds +(-1) '2;' /
    '  set ' ds ';' /    
    '  ' statements /
    'run;'
    ; 
run;

然后,您可以通過查看文件(在編輯窗口中使用“ include tempsas”命令)開始,提交一個數據步驟以查看一切是否正常,並在確定一切正常后,將

%include tempsas;

在您的原始代碼中。

在這里閱讀了注釋(感謝您的幫助!)之后,我想出了一個不同的解決方案(盡管更改宏以接受命名參數也可以):

data test3;
    set test2;
    statement=tranwrd(statement,"=",'%nrstr(=)');
    call execute('%dummy('||strip(ds)||','||strip(statement)||')');
run;

基本上,我只是將“代碼”更改為如下形式:

j1%nrstr(=)input(j,anydtdtm。); 放下j; 重命名j1%nrstr(=)j; k1%nrstr(=)input(k,anydtdtm。); 下降k; 重命名k1%nrstr(=)k; l1%nrstr(=)input(l,anydtdtm。); 降l; 重命名l1%nrstr(=)l;

我注意到如果我將宏更改為

%macro dummy(ds=,statements=);
data &ds.2;
  set &ds.;    
  &statements.
run;
%mend;

然后這個解決方案不起作用。 它說“找到的位置參數比定義的更多”。 有什么想法嗎?

因此,寧願將語句傳遞給宏,因為我假設您也正在生成要傳遞給宏的語句,所以我只會傳遞原始和所需的變量名,並使用數組。

%macro converter(var_in= , var_out=);
    data want;
      set data;
      array have(*) &var_in;
      array want(*) &var_out;

      do i=1 to dim(have);
         want(i)=input(have(i), anydtdtm.);
      end;
      drop &var_in;
     run;
 %mend;


 %converter(var_in= j1 k1 l1, var_out= j k l);

編輯:基於注釋的版本2。為簡化過程,我將變量重命名為temp1-temp {numvars},然后將它們重新編碼為所需的變量。 已成功測試。

%macro converter(var_in= j k l);
%let n_vars = %sysfunc(countw(&var_in));
    data want;
      set data (rename = (%do i=1 %to &n_vars;
                            %scan(&var_in, &i)=temp&i
                            %end;));
      array have(*) temp1-temp&n_vars.;
      array want(*) &var_in;

      do i=1 to dim(have);
         want(i)=input(have(i), anydtdtm.);
      end;
      drop temp1-temp&n_vars;
     run;
 %mend;

 %converter(var_in= j k l);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM