La manipulation de chaînes de caractères au sein du macro-langage nécessite une précision chirurgicale pour éviter les effets de bord, comme la suppression accidentelle de sous-chaînes. Cette macro %RemoveWords adopte une approche robuste en traitant la chaîne non pas comme un bloc de texte, mais comme une collection d'unités sémantiques distinctes (tokens). En utilisant une structure de boucles imbriquées couplée à la fonction %SCAN, elle garantit que seul le mot entier est comparé, préservant ainsi l'intégrité de termes similaires (par exemple, "low" ne sera jamais supprimé s'il fait partie du mot "flowers").
L'expertise technique s'exprime ici par la flexibilité du traitement de la casse. L'implémentation d'un commutateur casesens permet de basculer d'une comparaison stricte à une recherche insensible à la casse, un atout majeur pour normaliser des listes de variables ou des paramètres textuels issus de sources hétérogènes. L'utilisation finale de %sysfunc(compbl()) assure une sortie propre en éliminant les espaces doubles générés par les retraits successifs.
Une recommandation d'expert : pour des listes de mots très volumineuses, cette approche par boucles imbriquées peut devenir coûteuse en CPU. Dans ce cas, l'utilisation de la fonction PRXCHANGE avec une expression régulière construite dynamiquement ou le passage par la fonction TRANWRD sur des mots délimités pourrait offrir des performances supérieures.
Type : CREATION_INTERNE
La macro ne lit aucune donnée externe ou de SASHELP. Elle opère exclusivement sur les chaînes de caractères qui lui sont fournies en paramètres lors de son appel.
| 1 | %macro RemoveWords(string,targetwords,casesens=N); |
| 2 | |
| 3 | %local i j RESULT matchFlag NumTargetwords NumStringwords word targWord ; |
| 4 | |
| 5 | %IF not %LENGTH(&casesens.) %THEN %let casesens = N ; |
| 6 | %let casesens = %upcase(%substr(&casesens.,1,1)); |
| 7 | |
| 8 | %let NumStringwords = %words(&string.); |
| 9 | %let NumTargetwords = %words(&targetwords.); |
| 10 | |
| 11 | %DO i = 1 %to &NumStringwords. ; |
| 12 | %let matchFlag = 0 ; |
| 13 | %let word = %scan(&string.,&i.,%str( )); |
| 14 | %DO j = 1 %to &NumTargetwords. ; |
| 15 | %let targWord = %scan(&targetwords.,&j.,%str( )); |
| 16 | %IF (("&casesens." EQ "Y") AND ("&targWord." = "&word.")) OR ("%upcase(&targWord.)" = "%upcase(&word.)") %THEN %DO; |
| 17 | %let matchFlag = 1 ; |
| 18 | %let j = &NumTargetwords. ; |
| 19 | %END; |
| 20 | %END; |
| 21 | %IF (not &matchFlag.) %THEN %let RESULT = &RESULT. &word. ; |
| 22 | %END; |
| 23 | |
| 24 | %IF %LENGTH(&RESULT.) %THEN %let RESULT = %sysfunc(compbl(&RESULT.)); |
| 25 | &RESULT. |
| 26 | |
| 27 | %mend; |