CommunityRédaction et éditiongithub.com

sasjs/skills

Compétences d'agent pour l'écosystème SASjs et le langage de programmation SAS

Qu'est-ce que skills ?

Ce skill fournit aux agents IA un guide complet et idiomatique pour la génération et la révision de code SAS de qualité production. Il couvre l'ensemble des concepts fondamentaux du langage SAS, y compris la programmation DATA step (SET/MERGE/BY, tableaux, boucles DO, objets hash), PROC SQL (jointures, sous-requêtes, vues, passthrough), le langage macro (%macro/%mend, variables macro %local/%global) et les PROCédures courantes comme SORT, MEANS, FREQ, TRANSPOSE, REPORT, et FORMAT. Le skill est conçu pour fonctionner avec n'importe quel agent qui écrit du code SAS (Claude Code, Cursor, Codex, etc.) et met en œuvre une boucle de travail en cinq étapes : analyser la demande, rédiger le code, l'exécuter ou le décrire, inspecter le journal, et vérifier l'absence d'erreurs. Une règle non négociable impose zéro avertissement (WARNING) dans le journal, ce qui force l'agent à traiter chaque avertissement comme un défaut. Le guide inclut des règles de style strictes dérivées des normes @sasjs/core, des exemples avant/après pour les motifs courants générant des avertissements, et une liste de vérification des pièges fréquents. Il est particulièrement utile pour les développeurs qui automatisent la création ou la maintenance de code SAS avec des agents IA, car il garantit une qualité de code cohérente et évite les erreurs subtiles de type conversion implicite, troncature de variables, ou problèmes de portée des macros.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add sasjs/skills

Installed? Explore more Rédaction et édition skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Langage SAS

Écrivez du code SAS idiomatique et de qualité production. Ce skill couvre le langage SAS lui-même, indépendamment de tout framework.

Portée

  • Programmation DATA step (SET/MERGE/BY, RETAIN, tableaux, boucles DO, objets hash, traitement first./last.)
  • PROC SQL (jointures, sous-requêtes, vues, passthrough avec CONNECT TO)
  • Langage macro (%macro/%mend, variables macro, %local/%global, logique conditionnelle %IF, fonctions de quotation %STR/%NRSTR/%BQUOTE, CALL SYMPUTX)
  • PROCédures courantes : SORT, MEANS/SUMMARY, FREQ, TRANSPOSE, REPORT, PRINT, CONTENTS, DATASETS, FORMAT, IMPORT/EXPORT
  • Formats et informats (définis par l'utilisateur via PROC FORMAT, formats picture)
  • Sortie ODS (HTML, PDF, RTF, Excel, destination OUTPUT)
  • Entrées/Sorties fichier : LIBNAME, FILENAME, INFILE/INPUT, FILE/PUT

Workflow

Appliquez cette boucle à chaque demande qui produit du code SAS — nouveau programme, modification ou débogage :

  1. Analysez la demande. Identifiez les entrées : jeux de données, colonnes, variables macro, plateforme (SAS 9 vs Viya). Notez la sortie souhaitée : un jeu de données, un rapport (ODS), une variable macro, un fichier. Si la demande est ambiguë, énoncez votre hypothèse et poursuivez.
  2. Rédigez le code. Écrivez le programme minimal correct en suivant les règles de style ci-dessous. Utilisez des noms de jeux de données à deux niveaux, un length explicite pour les variables caractères, %local à l'intérieur des macros, et quit; pour proc sql. Préférez proc sort nodupkey à une dé duplication manuelle.
  3. Exécutez-le (ou décrivez l'exécution). Si une session SAS est disponible, soumettez et capturez le journal. Sinon, tracez le code mentalement par rapport à la liste des pièges courants — signalez toute étape que vous n'avez pas pu vérifier.
  4. Inspectez le journal. Considérez tout WARNING: ou ERROR: comme un défaut à corriger, pas une note à ignorer. Causes courantes : variables non initialisées, conversion implicite numérique→caractère, troncature due à une longueur implicite = 8, « aucune observation », références macro non résolues, variables macro automatiques en lecture seule. Les NOTE superflues doivent également être réduites lorsque c'est raisonnable.
  5. Vérifiez par rapport aux pièges. Relisez le code final par rapport à la liste des pièges courants avant de le renvoyer. Corrigez ou annotez tout ce qui est signalé.

Entrées : une demande (langage naturel ou fichier .sas), éventuellement des données d'exemple ou un extrait de journal. Sorties : code SAS idiomatique (indentation à 2 espaces, terminé par run;/quit;) plus, si utile, une courte note sur tout piège traité ou hypothèse formulée. Vérification : le code renvoyé passe un scan mental du journal avec zéro WARNING/ERROR, et une exécution réelle (quand disponible) produit un journal propre.

Non négociable : aucun WARNING

Le code SAS généré doit s'exécuter proprement — zéro WARNING (et zéro ERROR) dans le journal. Traitez chaque WARNING: comme un défaut : variables non initialisées, conversions de type implicites, notes de troncature qui devraient être des avertissements, « aucune observation », références macro non résolues, etc. Si un avertissement est vraiment inévitable, supprimez-le délibérément (par exemple avec une option explicite) et commentez pourquoi. Évitez également les NOTES superflues lorsque c'est raisonnable.

Règles de style

Ces règles suivent les normes de codage @sasjs/core — appliquez-les à tout code SAS :

  • Une instruction par ligne ; indentation = 2 espaces, pas de tabulations, pas d'espaces de fin de ligne
  • Lignes ne dépassant pas 80 caractères ; fins de ligne Unix (LF) ; UTF-8
  • Évitez complètement les caractères non-ASCII / spéciaux — compatibilité maximale entre les installations et codages SAS
  • Terminez toujours les étapes par run; ; pour proc sql (et les procédures connectées à CAS), quit; est essentiel pour éviter WARNING: You cannot disconnect or terminate session ... sur Viya
  • Toutes les références à des jeux de données doivent être à deux niveaux (work.blah, pas blah) — protège contre DATASTMTCHK=ALLKEYWORDS et une bibliothèque USER active
  • Utilisez un length / attrib explicite pour les variables caractères plutôt que de vous fier aux valeurs par défaut (évite la troncature implicite à longueur=8)
  • Utilisez des suffixes littéraux pour la clarté ('01JAN2020'd, '12:30't)
  • Préférez proc sort avec nodupkey à la logique de dé duplication manuelle
  • Macros :
    • Définissez avec des parenthèses, même sans paramètres : %macro x(); pas %macro x;
    • Le %mend; de fermeture doit répéter le nom de la macro
    • Les appels de macro ne se terminent pas par un point-virgule : %my_macro() pas %my_macro();
    • Paramètres obligatoires positionnels ; paramètres optionnels de style mot-clé (var=)
    • Noms de macro en minuscules, convention verbe-nom
    • Variables macro sans point final (&var pas &var.) sauf si nécessaire pour éviter une résolution incorrecte
    • Les NOMS des variables macro sont insensibles à la casse : &Foo, &FOO et &foo résolvent tous au même symbole (idem pour les arguments %symexist/%superq/symget, qui prennent un NOM pas une valeur). Ne cherchez pas les différences de casse comme un bogue — ce n'est jamais la cause.
    • TOUTES les variables macro doivent être %local sauf si délibérément globales (les globales doivent utiliser un préfixe d'application pour éviter les collisions) ; utilisez call symputx (pas symput) dans les DATA steps
    • Commentez avec /* */ à l'intérieur des macros (les commentaires astérisque sont compilés dans la macro)
    • Protégez la logique des macros avec des vérifications %length(&var)=0 plutôt que &var= (les comparaisons vides ne sont pas sûres)
  • Évitez les collisions de noms : utilisez des tables de travail basées sur %sysfunc-/&syslast (par exemple data &output; set &syslast; run;) plutôt que des noms codés en dur
  • La bibliothèque WORK est automatiquement effacée à la fin de la session : SAS supprime toutes les tables de WORK lorsque la session se termine, donc un nettoyage explicite (proc datasets lib=work nolist; delete ...; quit;) n'est pas requis pour les tables temporaires ordinaires — ne l'ajoutez pas, et ne signalez pas son absence comme un défaut lors de la révision. Nettoyez explicitement uniquement lorsque les fichiers temporaires sont volumineux ou nombreux au point de risquer une pression sur le disque en cours d'exécution ; dans ce cas, supprimez-les dès qu'ils ne sont plus nécessaires plutôt que de les laisser pour la fin de session.
  • Pas de code conditionnel ouvert (non macro) : enveloppez les blocs de branchement ou d'exécution conditionnelle de plateforme (par exemple %if %mf_getplatform()=VIYA %then %do; ... %end;) dans une %macro ... %mend et invoquez la macro. Un %if ouvert au niveau du programme échoue dans certains contextes d'exécution (jobs/scheduler/bancs de test) et cache des fuites de portée.

Sensibilisation à la portabilité

  • Notez quand le code diffère entre SAS 9.4 et Viya (par exemple actions CAS vs procédures, proc casutil pour le chargement sashdat, pas de commande X sur les serveurs verrouillés)
  • Évitez les chemins physiques codés en dur et les options spécifiques au moteur sauf demande explicite
  • Pas de code macro ouvert avec une logique if/else : enveloppez les blocs de branchement dans %macro ... %mend et appelez-les — un %if/%else ouvert ne se comporte pas comme prévu dans tous les environnements SAS.

Exemples avant / après

Chaque paire montre un motif courant générateur de WARNING ou de défaut et la correction idiomatique, avec le problème de journal qu'il résout.

DATA step : variable non initialisée + troncature de longueur implicite

Avant — region est référencée mais jamais assignée ni importée via set, donc le journal montre WARNING: Variable region is uninitialized ; et name hérite de la longueur de first_name de la source (souvent $8), tronquant silencieusement la valeur concaténée :

data work.customers;
  set work.source;
  region = upcase(region);                 /* region pas dans work.source */
  name = catx(' ', first_name, last_name); /* tronqué à la longueur source de name */
run;

Après — region est importée via set (ou assignée explicitement), et un length explicite avant set élargit name pour que catx ne soit pas tronqué :

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

PROC SQL : conversion implicite + produit cartésien

Avant — la jointure sur id caractère vs cust_id numérique déclenche NOTE: Character values have been converted to numeric (ou un WARNING sous certaines options), et la clé de jointure manquante risque une explosion cartésienne :

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;

Après — length/cast explicite pour que les types correspondent, jointure interne explicite, et une protection contre le produit cartésien si les clés manquent :

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 explicite ; ou corriger la longueur en amont */
  ;
quit;

Si une colonne de clé a légitimement des doublons des deux côtés, agrégez ou dédoublonnez d'abord — ne comptez jamais sur une jointure 1:1 accidentelle.

Macro : %local manquant + vérification vide dangereuse

Avant — %let à l'intérieur de la macro crée dsid dans la portée globale (pas de %local), et %if &filter= est dangereux — quand &filter est vide, cela se résout en %if = %then, une erreur de syntaxe plutôt qu'une branche propre :

%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;

Après — %local dsid garde la variable temporaire dans la portée de la macro, %length(&filter)=0 protège la vérification vide en toute sécurité, des parenthèses sur la définition de la macro, et %mend répète le nom :

%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;

Pièges courants à signaler lors de la révision

  • Jointures MERGE plusieurs-à-plusieurs non intentionnelles
  • Surprises de la variable automatique _ERROR_ / RETAIN implicite
  • Problèmes de timing de macro : référence à &macrovar avant son existence, %if évaluant des variables DATA step (utilisez if/symget à la place)
  • Les variables macro automatiques (&syscc, &syswarningtext, &syserrortext, &sysdate, &sysuserid, etc.) sont EN LECTURE SEULE — tenter de les écraser (par exemple %let syswarningtext=; ou call symput('syscc',...)) génère ERROR: Unable to assign value to a macro variable that is read only (ou similaire). N'essayez jamais de les « effacer ».
  • Troncature due à une longueur implicite = 8 lors de la première affectation
  • Avertissements de produit cartésien dans proc sql

Limites

Ce skill est une référence de langage statique — il fournit des conseils pour écrire et réviser du code SAS. Il n'exécute pas de code SAS, n'exécute pas de commandes shell, n'accède pas au système de fichiers, ne se connecte pas à des bases de données et n'effectue pas de requêtes réseau. Tous les exemples de code sont illustratifs et doivent être soumis à une session SAS par l'utilisateur. Les termes comme « Entrées/Sorties fichier », « PROC SQL », « commande » et « exécution » font référence à des concepts du langage SAS (instructions de gestion de fichiers, procédure SQL, contextes d'exécution de macros), pas à des opérations au niveau du système d'exploitation effectuées par ce skill.

Skills associés