Я пытаюсь добавить строковую макропеременную к имени набора данных в SAS. Я хочу создать наборы данных, которые читаются как work.cps2020jan и work.cps2020feb. Но это не то, что я получаю. Мой код:
%macro loop(values);
%let count=%sysfunc(countw(&values));
%do i = 1 %to &count;
%let value=%qscan(&values,&i,%str(,));
%put &value;
data work.cps2020&value.;
set "A:\cpsb2020&value" ;
mth = "&value.";
keep
PEMLR
mth
;
run;
%end;
%mend;
%loop(%str(jan,feb));
Запуск этого кода приводит к следующему выводу в журнале:
NOTE: There were 138697 observations read from the data set
A:\cpsb2020jan.
NOTE: The data set WORK.CPS2020 has 138697 observations and 2 variables.
NOTE: The data set WORK.JAN has 138697 observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 4.29 seconds
cpu time 0.20 seconds
feb
NOTE: There were 139248 observations read from the data set
A:\cpsb2020feb.
NOTE: The data set WORK.CPS2020 has 139248 observations and 2 variables.
NOTE: The data set WORK.FEB has 139248 observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 4.44 seconds
cpu time 0.15 seconds
Я не понимаю, почему мой макрос создает два набора данных на цикл вместо одного набора данных на цикл с именами work.cps2020jan и work.cps2020feb. Если я изменю &value. к &i. SAS выводит work.cps20201 и work.cps20202. Но это не то, чего я хочу.
Любые идеи?
&value
возвращается, как указано %qscan()
. Вместо этого используйте %scan()
. Переменные макроса в кавычках могут иногда вызывать проблемы при разрешении, когда они используются таким образом. Лучше цитировать их только тогда, когда это необходимо, например, в выражении %put
со знаком % внутри него.
Вам не нужно %qscan()
. Если бы значение содержало какие-либо символы, требующие заключения макроса в кавычки, то они в любом случае были бы недопустимы для использования в имени члена. Так что используйте %scan()
вместо этого.
Но при использовании внутри макроса токенизатор иногда ошибочно воспринимает такие вещи, как xxx&mvar
, как два токена, даже если в &mvar
нет специальных символов. Вы можете сгруппировать значение, которое вы создаете, чтобы обойти это.
Например, создав новую макропеременную
%let dsn=cps2020&value.;
data work.&dsn. ;
Или используйте функцию %unquote()
:
data %unquote(work.cps2020&value.);
Или используйте литерал имени:
data work."cps2020&value."n;
Функция макроса %QSCAN
замаскирует результат специальными невидимыми (непечатаемыми) символами, видимыми только для системы макропроцессора.
Что случилось, так это
data work.cps2020&value.;
рассматривался как
data work.cps2020<mask-character><non-masked part of symbol value><mask-character>;
во время обработки исполнителем, который обрабатывал непечатаемый символ маски как несинтаксический разделитель токенов, в результате чего был получен оператор DATA
со списком двух выходных таблиц.
data work.cps2020 jan;
Положения символов маски в макропеременной можно наблюдать (в журнале) с помощью %put _user_
, или фактическое содержимое символа можно захватить из представления метаданных, такого как SASHELP.VMACRO
или DICTIONARY.MACRO
Давайте упростим ваш макрос и добавим журналирование и захват символов
%macro loop(values);
%local count i;
%let count=%sysfunc(countw(&values));
%do i = 1 %to &count;
%let value=%qscan(&values,&i,%str(,));
%put _user_; %*--- log them masks;
data x&i; %* --- symbol capture;
set sashelp.vmacro;
where name like '%VALUE%';
value_hex = put (value,$HEX40.);
run;
%* --- do the step that creates two tables;
data work.cps2020&value.;
set sashelp.class;
run;
%end;
%mend;
options nomprint nosymbolgen nomlogic;
%loop(%str(jan,feb));
proc print data=x1 noobs style(data)=[fontsize=14pt fontfamily = "Courier"];
var value:;
run;
Фрагмент LOG, эти маленькие прямоугольники представляют собой специальные невидимые маскирующие символы (я показываю их на снимках изображений, потому что переполнение стека / html не отображает непечатаемые символы)
Тот же текст LOG, скопированный и вставленный в Notepad2, показывает символы маски как управляющие символы
Proc PRINT
захваченных данных символа макроса будет отображать шестнадцатеричные маскирующие символы.
06
запуск макроса %quote08
макрос %quote конец01
запуск макроса %str02
макрос %str конец1E
скрытая версия запятойВау - это было здорово, спасибо! После замены qscan() на scan() макрос сделал то, что я хотел (перебрать список строк и добавить строку к имени набора данных).
Отличное объяснение