Зацикливание набора макросов - PullRequest
0 голосов
/ 30 апреля 2018

Я пытаюсь создать цикл таким образом, чтобы я запускал два макроса для каждого набора данных

%Let Classification  = Data1 data2 data3 data4; 

%let index  = 1;

%do %until (%Scan(&Classification,&index," ")=);

%Macro1;
%Macro2;

%end;

%let index  = %eval(&Index  + 1);

Проблема в том, что мои макросы предварительно не загружены и хранятся в библиотеке макросов. Можно ли это сделать, если я запустил вышеупомянутый макрос как макрос?

Любой совет в том, чтобы этот цикл макросов работал

EDIT:

В моей идеальной ситуации цикл работал бы как макрос

%Macro;

где внутри это будет выглядеть

%Macro Macro;

%let index = 1;

%do %until (%scan(&classification,&index," ")=);

<Lines of Code>

%end;

%let index = %eval(&Index + 1);

%end;

%mend;

Другая проблема заключается в том, что мои макросы, заключенные в цикл, используют & классификацию, чтобы различать данные1, данные2, данные3, данные4 при обработке различных строк кода.

Ответы [ 3 ]

0 голосов
/ 30 апреля 2018

SAS не допускает оператор %DO в открытом коде. Когда вы отправляете цикл открытого кода, вы получите сообщения журнала

ERROR: The %DO statement is not valid in open code.
...
ERROR: The %END statement is not valid in open code.

как упомянул @Tom, макрос %SCAN должен проверять наличие нулевой строки. Другим распространенным и более надежным способом является проверка перед извлечением токена. %do %until будет плохо повторяться, когда пройденная классификация будет пустой. A %do %while проверяет сканирование classification перед вызовами внутренних макросов. Другим распространенным тестом для нулевого значения макроса является проверка длины 0 и усиление 0 = ложь ^ 0 = истинная автоматическая оценка.

Когда цикл должен вызывать другие макросы со значением токена, лучше всего передавать значение токена вместо того, чтобы вызываемый макрос предполагал, что символ токена (он же макропеременная) уже существует (в содержащей области) до итерированного вызов макроса.

Пример

%macro mydispatch (classification=);

  %local index token;
  %let index = 1;
  %do %while ( %length (%scan (&classification, &index)));
    %let token = %scan(&classification,&index));

    %* emit code specifically for token;
    * this is for &token;

    %* iterated invocations, perform two analysis for each data set listed in classification;        
    %* second analysis is passed another argument specifying the data set that should be used to store output;
    %analysis_1 (data=&token)
    %analysis_2 (data=&token, out=WORK.results_&token.)

    %let index = %eval(&index+1);
  %end;
%mend mydispatch;

%mydispatch (classification=data1 data2 data3 data4)
0 голосов
/ 30 апреля 2018

Вероятно, проще просто перебрать индекс. Используйте функцию countw(), чтобы узнать, сколько итераций нужно сделать.

%macro loop(list);
%local index next ;
%do index=1 %to %sysfunc(countw(&list,%str( )));
  %let next=%scan(&list,&index,%str( ));
  ... code to process &NEXT ...
%end;
%mend ;

Затем передайте список макросу в качестве значения параметра.

%Let Classification  = Data1 data2 data3 data4; 
%loop(&classification);
0 голосов
/ 30 апреля 2018

Макрос, находящийся в библиотеке автозвонков (на что, я полагаю, вы ссылаетесь?), Никак не влияет на то, как это будет работать. Если он не находится в библиотеке авто-вызовов, вам придется сначала подключить каталог к ​​библиотеке авто-вызовов.

В ре: ваши правки; да, вам нужно, чтобы это было в макросе (изначально я предполагал, что это подмножество макроса). %do в настоящее время не разрешено в открытом коде (это может измениться, но не сегодня).

Обратите внимание, что в вашем коде есть несколько существенных проблем:

  • инкрементор не находится в цикле
  • функция сканирования неправильная; язык макросов не использует кавычки, поэтому

    %do %until (%Scan(&Classification,&index," ")=);

    должно быть

    %do %until (%Scan(&Classification,&index)=);

    (пробел является разделителем по умолчанию), и если вам действительно нужно уточнить пробел:

    %do %until (%Scan(&Classification,&index,%str( ))=);

  • Ваши макросы не используют параметры; им следует. %macro1; очевидно использует &classification и &index; вместо этого вы должны передать ему нужную вещь («слово» из &classification) в качестве параметра.

...