CommunityEscrita e Ediçãogithub.com

sasjs/skills

Habilidades do agente para o ecossistema SASjs e a linguagem de programação SAS

O que é skills?

Este skill fornece um guia completo para escrever código SAS idiomático e de produção, cobrindo desde a programação DATA Step e PROC SQL até a linguagem macro e PROCs comuns. Ele é útil para desenvolvedores que desejam gerar código SAS correto e eficiente, evitando erros comuns como variáveis não inicializadas, conversões implícitas de tipo e truncamento. O skill é compatível com os ambientes SAS 9 e Viya, e seu fluxo de trabalho orienta o agente a analisar a solicitação, redigir o código, inspecionar o log e revisar contra uma lista de armadilhas comuns. Embora não execute código SAS, ele serve como uma referência estática para a criação e revisão de código, garantindo que o código gerado não produza WARNINGs ou ERRORs no log.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add sasjs/skills

Installed? Explore more Escrita e Edição skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Linguagem SAS

Escreva código SAS idiomático e de produção. Este skill abrange a linguagem SAS em si, independente de qualquer framework.

Escopo

  • Programação DATA Step (SET/MERGE/BY, RETAIN, arrays, loops DO, objetos hash, processamento first./last.)
  • PROC SQL (joins, subconsultas, views, pass-through com CONNECT TO)
  • Linguagem macro (%macro/%mend, variáveis macro, %local/%global, lógica condicional %IF, funções de quoting %STR/%NRSTR/%BQUOTE, CALL SYMPUTX)
  • PROCs comuns: SORT, MEANS/SUMMARY, FREQ, TRANSPOSE, REPORT, PRINT, CONTENTS, DATASETS, FORMAT, IMPORT/EXPORT
  • Formats e informats (definidos pelo usuário via PROC FORMAT, picture formats)
  • Saída ODS (HTML, PDF, RTF, Excel, destino OUTPUT)
  • E/S de arquivos: LIBNAME, FILENAME, INFILE/INPUT, FILE/PUT

Fluxo de trabalho

Aplique este loop a cada solicitação que produza código SAS — novo programa, edição ou depuração:

  1. Analise a solicitação. Identifique as entradas: datasets, colunas, variáveis macro, plataforma (SAS 9 vs Viya). Observe a saída desejada: um dataset, um relatório (ODS), uma variável macro, um arquivo. Se a solicitação for ambígua, declare sua suposição e prossiga.
  2. Elabore o código. Escreva o programa mínimo correto seguindo as regras de Estilo abaixo. Use nomes de dataset de 2 níveis, length explícito para variáveis caractere, %local dentro de macros e quit; para proc sql. Prefira proc sort nodupkey em vez de dedup manual.
  3. Execute (ou descreva a execução). Se uma sessão SAS estiver disponível, submeta e capture o log. Caso contrário, percorra o código mentalmente contra a lista de Armadilhas comuns — aponte qualquer etapa que não pôde verificar.
  4. Inspecione o log. Trate qualquer WARNING: ou ERROR: como um defeito a ser corrigido, não uma nota a ser ignorada. Culpados comuns: variáveis não inicializadas, conversão numérico→caractere implícita, truncamento devido a length implícito=8, "no observations", referências de macro não resolvidas, variáveis macro automáticas somente leitura. NOTEs supérfluos também devem ser cortados quando razoável.
  5. Revise contra armadilhas. Releia o código final contra a lista de Armadilhas comuns antes de retorná-lo. Corrija ou anote qualquer item sinalizado.

Entradas: uma solicitação (linguagem natural ou um arquivo .sas), opcionalmente dados de amostra ou um trecho de log. Saídas: código SAS idiomático (indentado com 2 espaços, terminado com run;/quit;) além de, quando útil, uma breve nota sobre qualquer armadilha abordada ou suposição feita. Verificação: o código retornado passa por uma varredura mental do log com zero WARNING/ERROR, e uma execução real (quando disponível) produz um log limpo.

Inegociável: sem WARNINGs

O código SAS gerado deve ser executado de forma limpa — zero WARNINGs (e zero ERRORs) no log. Trate cada WARNING: como um defeito: variáveis não inicializadas, conversões de tipo implícitas, notas de truncamento que deveriam ser warnings, "no observations", referências de macro não resolvidas, etc. Se um warning for verdadeiramente inevitável, suprima-o deliberadamente (ex.: uma opção explícita) e comente o porquê. Da mesma forma, evite NOTEs supérfluos quando razoável.

Regras de estilo

Estas seguem os padrões de codificação @sasjs/core — aplique-as a todo código SAS:

  • Uma instrução por linha; indentação = 2 espaços, sem tabs, sem espaços em branco à direita
  • Linhas com no máximo 80 caracteres; fim de linha unix (LF); UTF-8
  • Evite caracteres não-ASCII / especiais completamente — máxima compatibilidade entre instalações e codificações SAS
  • Sempre termine etapas com run;; para proc sql (e procs conectados ao CAS) quit; é essencial para evitar WARNING: You cannot disconnect or terminate session ... no Viya
  • Todas as referências a datasets devem ser de 2 níveis (work.blah, não blah) — protege contra DATASTMTCHK=ALLKEYWORDS e uma biblioteca USER ativa
  • length / attrib explícito para variáveis caractere em vez de depender de padrões (evita truncamento por comprimento implícito=8)
  • Use sufixos literais para clareza ('01JAN2020'd, '12:30't)
  • Prefira proc sort com nodupkey em vez de lógica de dedup manual
  • Macros:
    • Defina com parênteses, mesmo sem parâmetros: %macro x(); não %macro x;
    • %mend; de fechamento deve repetir o nome da macro
    • Chamadas de macro não são terminadas com ponto e vírgula: %my_macro() não %my_macro();
    • Parâmetros obrigatórios posicionais; parâmetros opcionais no estilo palavra-chave (var=)
    • Nomes de macro em minúsculas, convenção verbo-substantivo
    • Variáveis macro sem ponto final (&var não &var.) a menos que necessário para evitar resolução incorreta
    • NOMES de variáveis macro não diferenciam maiúsculas de minúsculas: &Foo, &FOO e &foo todos resolvem para o mesmo símbolo (o mesmo para argumentos de %symexist/%superq/symget, que recebem um NOME, não um valor). Não persiga incompatibilidades de maiúsculas como um bug — nunca é a causa.
    • TODAS as variáveis macro devem ser %local a menos que deliberadamente globais (globais devem usar um prefixo de aplicativo para evitar colisões); use call symputx (não symput) em etapas DATA
    • Comente com /* */ dentro de macros (comentários com asterisco são compilados na macro)
    • Proteja a lógica macro com verificações %length(&var)=0 em vez de &var= (comparações vazias são inseguras)
  • Evite colisões de nomenclatura: use tabelas de trabalho baseadas em %sysfunc-/&syslast (ex.: data &output; set &syslast; run;) em vez de nomes fixos
  • A biblioteca WORK é limpa automaticamente no término da sessão: o SAS exclui todas as tabelas no WORK quando a sessão termina, portanto, limpeza explícita (proc datasets lib=work nolist; delete ...; quit;) não é necessária para tabelas temporárias comuns — não a adicione, e não sinalize sua ausência como um defeito na revisão. Limpe explicitamente apenas quando os arquivos temporários forem grandes ou volumosos o suficiente para arriscar pressão no disco durante a execução; nesse caso, descarte-os assim que não forem mais necessários, em vez de deixá-los para descarte no final da sessão.
  • Sem código condicional aberto (não-macro): envolva blocos de ramificação de plataforma ou execução condicional (ex.: %if %mf_getplatform()=VIYA %then %do; ... %end;) em um %macro ... %mend e invoque a macro. %if aberto em nível de programa falha em alguns contextos de execução (jobs/schedulers/test harnesses) e esconde vazamentos de escopo.

Consciência de portabilidade

  • Observe quando o código difere entre SAS 9.4 e Viya (ex.: ações CAS vs procs, proc casutil para carregamento sashdat, nenhum comando X em servidores bloqueados)
  • Evite caminhos físicos codificados e opções específicas de engine, a menos que solicitado
  • Sem código macro aberto com lógica if/else: envolva blocos de ramificação em %macro ... %mend e chame-os — %if/%else aberto não se comporta como esperado em todos os ambientes SAS.

Exemplos antes / depois

Cada par mostra um padrão comum propenso a WARNING ou defeito e a correção idiomática, com o problema de log que aborda.

DATA Step: variável não inicializada + truncamento por comprimento implícito

Antes — region é referenciada mas nunca atribuída ou trazida via set, então o log mostra WARNING: Variable region is uninitialized; e name herda o comprimento de first_name da fonte (frequentemente $8), truncando silenciosamente o valor concatenado:

data work.customers;
  set work.source;
  region = upcase(region);                 /* region não está em work.source */
  name = catx(' ', first_name, last_name); /* truncado para o comprimento da fonte de name */
run;

Depois — region é trazida via set (ou atribuída explicitamente), e um length explícito antes de set aumenta name para que catx não seja truncado:

data work.customers;
  length name $ 50;
  set work.source;                          /* region deve existir em work.source */
  region = upcase(region);
  name = catx(' ', first_name, last_name);
run;

PROC SQL: conversão implícita + produto cartesiano

Antes — juntar em id caractere vs cust_id numérico dispara NOTE: Character values have been converted to numeric (ou um WARNING sob algumas opções), e a chave de junção ausente arrisca uma explosão cartesiana:

proc sql;
  create table work.joined as
  select a.*, b.balance
  from work.orders a, work.accounts b
  where a.id = b.cust_id;
quit;

Depois — length/cast explícito para que os tipos correspondam, inner join explícito e uma proteção contra o cartesiano se as chaves estiverem faltando:

proc sql;
  create table work.joined as
  select a.id, a.amount, b.balance
  from work.orders as a
  inner join work.accounts as b
    on a.id = input(b.cust_id, 8.) /* cast explícito; ou corrija o comprimento upstream */
  ;
quit;

Se uma coluna de chave tiver duplicatas legítimas em ambos os lados, agregue ou dedupe primeiro — nunca confie em um join 1:1 acidental.

Macro: %local ausente + verificação de vazio insegura

Antes — %let dentro da macro cria dsid no escopo global (sem %local), e %if &filter= é inseguro — quando &filter está vazio, resolve para %if = %then, um erro de sintaxe em vez de um branch limpo:

%macro apply_filter(filter=);
  %if &filter= %then %do;
    data work.out; set work.in; run;
  %end;
  %else %do;
    data work.out; set work.in; where &filter; run;
  %end;
  %let dsid = &syslast;
%mend apply_filter;

Depois — %local dsid mantém a variável temporária no escopo da macro, %length(&filter)=0 protege a verificação de vazio com segurança, parênteses na definição da macro e %mend repete o nome:

%macro apply_filter(filter=);
  %local dsid;
  %if %length(&filter)=0 %then %do;
    data work.out; set work.in; run;
  %end;
  %else %do;
    data work.out; set work.in; where &filter; run;
  %end;
  %let dsid = &syslast;
%mend apply_filter;

Armadilhas comuns a sinalizar ao revisar

  • MERGEs muitos-para-muitos não intencionais
  • Surpresas com variável automática _ERROR_ / RETAIN implícito
  • Problemas de temporização macro: referenciar &macrovar antes de existir, %if avaliando variáveis do data step (use if/symget em vez disso)
  • Variáveis macro automáticas (&syscc, &syswarningtext, &syserrortext, &sysdate, &sysuserid, etc.) são SOMENTE LEITURA — tentar sobrescrevê-las (ex.: %let syswarningtext=; ou call symput('syscc',...)) gera ERROR: Unable to assign value to a macro variable that is read only (ou similar). Nunca tente "limpá-las".
  • Truncamento devido a comprimento implícito=8 na primeira atribuição
  • Avisos de produto cartesiano em proc sql

Limitações

Este skill é uma referência de linguagem estática — fornece orientação para escrever e revisar código SAS. Ele não executa código SAS, executa comandos shell, acessa o sistema de arquivos, conecta-se a bancos de dados ou faz requisições de rede. Todos os exemplos de código são ilustrativos e devem ser submetidos a uma sessão SAS pelo usuário. Termos como "E/S de arquivos", "PROC SQL", "comando" e "execução" referem-se a conceitos da linguagem SAS (instruções de manipulação de arquivos, procedimento SQL, contextos de execução de macro), não a operações de nível de sistema operacional realizadas por este skill.

Habilidades Relacionadas