Создание макропеременных через CALL SYMPUT

Всем привет!

Данная статья — это голая калька с другой статьи.

К сожалению, на habrahabr.ru нету как такого раздела или публикаций на тему SAS. И искать там что-либо оказывается затруднительным, если не знаешь, что искать =)
Данный же ресурс целиком и полностью предназначен для SAS пользователей.


Краткая предыстория проблемы, решение которой пришлось сначала искать самому.
Задача считать название файлов из директории и записать их в другую директорию.

filename read1 ftp » ls lsfile=’*.txt’ cd=»» &ftp;
data read1;
    length name $ 60;
    infile read1;
    input name $;
run;

Тут возникает вопрос, как записать значение данной переменной в макропеременную так, чтобы обрезать хвост. Не стану вдаваться в подробности какие способы были использованы для решения данной проблемы, а вставлю текст, который сразу всё расставит на свои места.

Источник http://habrahabr.ru/post/142147/
За что автору большой плюс в его карму! =)

===============================================================
Добрый день, дорогие читатели.
В этой статье я расскажу о двух процедурах языка SAS Base и о небольших тонкостях их применения.

Тем, кто уже достаточно работает с этим языком, эти вещи покажутся элементарными, но для начинающих они, возможно, позволят избежать грабли, на которые я наступил в самом начале моего знакомства с SAS Base.

CALL SYMPUT

Call Symput используется для случаев, когда значение переменной в шаге данных (datastep) нужно присвоить макропеременной.
Синтаксис: call symput ("<макропеременная>", <символьное значение>)

Первый аргумент в процедуре symput — это название макропеременной, которой необходимо присвоить значение второго аргумента.

Второй аргумент — это символьное значение, которое будет присвоено макропеременной. Второй аргумент всегда должен быть именно символьным, в противном случае, численное значение должно быть конвертировано в символьную переменную, прежде чем присваивать его макропеременной. Если Вы не станете приводить тип, это может обернуться проблемами. В таком случае SAS автоматически конвертирует численное значение переменной в символьное значение, прежде чем присвоит его макропеременной, и выведет в лог сообщение о том, что было произведено конвертирование.

Пример:
data _null_;
count=1978;
call symput('count',count);
run;
%put &count;

19 data _null_;
20 count=1978;
21 call symput('count',count);
22 run;

NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).
21:21
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds

23 %put &count;
1978

Хоть значение макропеременной count и было определено как 1978, SAS выдал замечание, гласящее
NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).
21:21

Чтобы избежать этого, Вам всё же стоит осуществить конвертирование численного значения в символьное, прежде чем присваивать его макропеременной. Вот, например, как это можно сделать:

data _null_;
count=1978;
call symput('count',strip(put(count,8.)));
run;
%put &count;

29 data _null_;
30 count=1978;
31 call symput('count',left(put(count,8.)));
32 run;

NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

33 %put &count;
1978

Примечания:

  1. Несмотря на то, что мы создали переменную при помощи CALL SYMPUT, эта макропеременная не может быть использована напрямую в том же datastep’е. Причина такого явления — макро код компилируется и выполняется до того, как будет скомпилирован и выполнен datastep. Так что, макропеременная, создающаяся CALL SYMPUT, не будет доступна в datastep в силу того, что эта макропеременная будет создана и присвоена только после или во время выполнения кода datastep.
    (В случае, если Вам всё же понадобится доступ к той же макропеременной внутри datastep, Вы, разумеется, сумеете это сделать, при помощи двух разных макрофункций — RESOLVE или SYMGET)
  2. SAS всегда выравнивает численные значения по правому краю, что приводит к пробелам в начале символьной переменной при конвертации, если значение численной переменной было меньше её длины. Чтобы избавиться от этих пробелов, используйте функции, удаляющие все ведущие пробелы (как в примере выше).
  3. Если процедура CALL SYMPUT используется вне макроса (т.е. в открытом коде), она создаёт глобальную макропеременную, тогда как при использовании внутри макроса она создаст локальную.

CALL SYMPUTX

Процедура CALL SYMPUTX была анонсирована SAS в 9 версии с целью обойти ловушки CALL SYMPUT.
Преимущества CALL SYMPUTX перед CALL SYMPUT включают в себя:

  1. SYMPUTX автоматически конвертируют численные переменные в символьные перед присваиванием их макропеременной. (Вы больше не нуждаетесь в ручной конвертации при помощи выраждения PUT как в вышеприведённом примере)
  2. CALL SYMPUTX удаляет ведущие и хвостовые пробелы. Так что необходимость функций, наподобие STRIP или LEFT, для очистки от лишних пробелов, отпадает.

Синтаксис: call symputx ("<макропеременная>", <символьное значение>, <таблица символов>)

Первые два аргумента аналогичны аргументам CALL SYMPUT. Третий аргумент (таблица символов) опционален и может принимать значения G, L или F. Если Вы укажете G, макропеременная будет создана в глобальной таблице символов, если же Вы укажете L, SAS сохранит макропеременную в локальной таблице. Если третий аргумент не указывать или установить его как F, CALL SYMPUTX будет вести себя аналогично CALL SYMPUT.

Пример:
data _null_;
count=1978;
call symputx('count',count,’G’);
run;
%put &count;

29 data _null_;
30 count=1978;
31 call symputx('count',count,'G');
32 run;

NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

33 %put &count;
1978

Примечание: Если бы Вы использовали CALL SYMPUT вместо CALL SYMPUTX, программа выполнилась бы идентично, но в лог было бы выдано замечание об автоматической конвертации численного значения в символьное.

Простой способ запомнить разницу между CALL SYMPUT и CALL SYMPUTX:
(взято со страницы Using_the_SAS_V9_CALL_SYMPUTX_Routine на SAScommunity.org)

Процедура SAS V9 CALL SYMPUTX позволяет Вам сэкономить нажатия клавиш и создать более компактный и понятный код.
Вместо использования
call symput('macrovar', trim(left(charvar)));
для создания макропеременной с символьной строкой, которая может содержать лишние пробелы, Вам стоит применить SYMPUTX:
call symputx('macrovar', charvar);

Настройка SFTP в SAS 9.2-9.3

Доброго времени суток, уважаемые читатели!

В этой статье речь пойдёт об использовании доступа к SFTP серверам через ключ авторизации.
Хочу сразу отметить, что способ подключения достаточно похож с FTP, но имеет ряд нюансов с которыми придётся столкнуться.


Во-первых, для доступа к SFTP потребуется полностью установленный клиент Putty.
Во-вторых, требуется прописать путь к тому же Putty в системной переменной PATH.
В-третьих, нужно знание (синтаксиса) команд, которые передаются через psftp.exe.

Итак, общая схема подключения к серверу SFTP аналогична с FTP.
Для этого используется следующая структура:
FILENAME fileref SFTP ‘external-file‘ <sftp-options>; 
Основные настройки можно прочитать тут.

Пример:
filename example sftp «name» cdpath» hosthostname»
      options = ‘optionsuserusername» debug;

К сожалению, этого куска кода не достаточно, чтобы работать с SFTP. Всё дело в том, что разобраться с параметром options требует немало времени. По крайней мере до версии SAS 9.4.
В этот параметр записываются значения, которые использует программа PSFTP.EXE из стандартного набора putty.

Теперь по порядку:

  1. Устанавливаем полный клиент Putty.
  2. Прописываем путь в системной переменной PATH. Например для Windows Server 2008, правой кнопкой по значку мой компьютер -> Advanced System Properties ->  Environment Variables. Далее ищем среди системных переменных PATH и добавляем после точки с запятой путь, куда был установлен PUTTY. 
  3. Теперь можно использовать опции для настройки подсоединения по SFTP:
    • -V        печатает версию и выходит
    • -pgpfp печатает PGP fingerprints и выходит
    • -b file   использует batch файл (*.bat)
    • -bc      выводит на экран команды из batch файла
    • -be       игнорирует ошибки работы batchfile
    • -v        выводит подробные сообщения (лог)
    • -load sessname  использует данные предыдущей sessname (подключения)
    • -l user   соединение по определённому пользователю
    • -P port   соединение по определённому порту  
    • -pw passw соединение по определённому паролю 
    • -1 -2     использование SSH протокола версии 1 или 2
    • -4 -6     использование IPv4 или IPv6
    • -C       использование компрессии
    • -i key    private key для аутентификации 
    • -noagent  запрет использования Pageant  
    • -agent    использование Pageant  
    • -batch    запрет на любые интерактивные запросы

В итоге, приведу пример кода, если вы используете аутентификацию по ключу, подсоединяетесь по имени пользователя и определённому порту.
Пример кода для параметра options:

options =   ‘-P 666
                    -i c:private.ppk
                    -pw password’

Важно: ключевые  параметры (типа -P) чувствительны к регистру!!

Надеюсь, что статья оказалась полезна!
До скорых встреч!

Обработка нестандартных пробелов

Привет!

Я новый участник этого замечательного проекта. Мой опыт не такой богатый, как у Николая, но думаю, что мне есть чем поделиться.

Сегодня я хочу рассказать о возможной проблеме с длиной строк при импорте из Excel.


Допустим, вам необходимо залить табличку из Excel, в которой присутствуют русские символы. Например такого типа:

У вас есть несколько вариантов, но самый простой это процедура IMPORT:
libname temp «sas-directory»;
proc import
            out= temp.example
            datafile= «табличка.xlsx»
            dbms= XLSX replace;
     sheet=»test»;
     getnames=yes;
run;

И вроде бы всё нормально, но мы встречаемся с тем в строке появились ненужные дополнительные символы, которые при записи выглядят как пробелы.
Вы возможно скажете, что trim(varname) нам поможет, но, к сожалению, это не так.

Попробуем разобраться, обратимся к получившейся табличке и запишем значения переменной и значение, получившееся после функции trim:
data _null_;
    set temp.example (obs=1);
    file ‘d:sas_exampletemp.txt’;
    put var;
    k = trim(var);
    put k;
run;

Результат в блокноте:

Для удаления этих пробелов существует такая замечательная функция COMPRESS.
Кто-то скажет, что надо просто сделать COMPRESS(var, ’09’x), так как пробелы соответствуют значению 09 в таблице кодов, но данные пробелы не соответствуют коду ’09’x.

Кстати, если бы нам надо было удалить все специальные символы (в данном случае речь идёт о символах юникода), то можно было просто воспользоваться параметрами функции COMPRESS(var, ,’kw’). Но нам надо удалить конкретные значения.

Сначала выясним, какие значения нам необходимо удалить, записав каждый символ и его код отдельно:
 data _null_;
    set temp.example (obs=1);
    file ‘d:sas_exampletemp.txt’;
    do i = 1 to length(var);
        b = substr(var, i, 1);
        a = put(b,$HEX2.);
        put b a ;
    end;
run;

Вот что мы обнаружили:

Оказывается, за этими пробелами стоят значения ’00’x. Теперь мы можем удалить их все через функцию с параметром COMPRESS(var, ’00’x).

Спасибо за прочтение и до свидания!