mirror of
https://github.com/yabwon/SAS_PACKAGES.git
synced 2026-01-03 05:10:05 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df04e48656 | ||
|
|
76c7793e34 | ||
|
|
cc6528bbeb | ||
|
|
2bb633a55b |
@@ -122,7 +122,7 @@ SHA256 digest for DFA: 5F89AC6AE628EB27D87FF6A9D72A515FFA3FF6694D04DE0D9811BFFB8
|
||||
|
||||
[Documentation for DFA](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/dfa.md "Documentation for DFA")
|
||||
|
||||
- **macroArray**\[0.9\], implementation of an array concept in a macrolanguage, e.g.
|
||||
- **macroArray**\[1.0\], implementation of an array concept in a macrolanguage, e.g.
|
||||
```sas
|
||||
%array(ABC[17] (111:127), macarray=Y);
|
||||
|
||||
@@ -141,7 +141,7 @@ SHA256 digest for DFA: 5F89AC6AE628EB27D87FF6A9D72A515FFA3FF6694D04DE0D9811BFFB8
|
||||
which = 1:H:2
|
||||
);
|
||||
```
|
||||
SHA256 digest for macroArray: 833D747526F4CE83FFD73F9EB3A2A9065401B498DFEC79045A28A42E0E57A8CA
|
||||
SHA256 digest for macroArray: DAEB87654D99965BF2B7A6AB14626B3E617D0ABF526E77725DF89A1AB4C812C2
|
||||
|
||||
[Documentation for macroArray](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/macroarray.md "Documentation for macroArray")
|
||||
|
||||
@@ -168,12 +168,12 @@ SHA256 digest for BasePlus: A60A300E083628C65DD6899E7EF95588916F8F66B6A25B32B322
|
||||
|
||||
[Documentation for BasePlus](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md "Documentation for BasePlus")
|
||||
|
||||
- **GSM** (Generate Secure Macros)\[0.17\], package allows
|
||||
- **GSM** (Generate Secure Macros)\[0.19\], package allows
|
||||
to create secured macros stored in SAS Proc FCMP functions.
|
||||
The dataset with functions can be shared between different operating systems
|
||||
and allows to generate macros on site without showing their code.
|
||||
|
||||
SHA256 digest for GSM: 3B70D8C31F02CB2B6AC47CC1DB3EC9E462796226CBFF519936AF5EEDB0C46B8F
|
||||
SHA256 digest for GSM: F63B8C602C1DB02F4107D9AF78182D87CD64AEA6521163067B7EB6D5C1B368AF
|
||||
|
||||
[Documentation for GSM](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/gsm.md "Documentation for GSM")
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -65,7 +65,7 @@ SHA256 digest for DFA: 5F89AC6AE628EB27D87FF6A9D72A515FFA3FF6694D04DE0D9811BFFB8
|
||||
|
||||
---
|
||||
|
||||
- **macroArray**\[0.9\], implementation of an array concept in a macro language, e.g.
|
||||
- **macroArray**\[1.0\], implementation of an array concept in a macro language, e.g.
|
||||
```sas
|
||||
%array(ABC[17] (111:127), macarray=Y);
|
||||
|
||||
@@ -84,7 +84,7 @@ SHA256 digest for DFA: 5F89AC6AE628EB27D87FF6A9D72A515FFA3FF6694D04DE0D9811BFFB8
|
||||
which = 1:H:2
|
||||
);
|
||||
```
|
||||
SHA256 digest for macroArray: 833D747526F4CE83FFD73F9EB3A2A9065401B498DFEC79045A28A42E0E57A8CA
|
||||
SHA256 digest for macroArray: DAEB87654D99965BF2B7A6AB14626B3E617D0ABF526E77725DF89A1AB4C812C2
|
||||
|
||||
[Documentation for macroArray](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/macroarray.md "Documentation for macroArray")
|
||||
|
||||
@@ -114,12 +114,12 @@ SHA256 digest for BasePlus: A60A300E083628C65DD6899E7EF95588916F8F66B6A25B32B322
|
||||
|
||||
---
|
||||
|
||||
- **GSM** (Generate Secure Macros)\[0.17\], package allows
|
||||
- **GSM** (Generate Secure Macros)\[0.19\], package allows
|
||||
to create secured macros stored in SAS Proc FCMP functions.
|
||||
The dataset with functions can be shared between different operating systems
|
||||
and allows to generate macros on site without showing their code.
|
||||
|
||||
SHA256 digest for GSM: 3B70D8C31F02CB2B6AC47CC1DB3EC9E462796226CBFF519936AF5EEDB0C46B8F
|
||||
SHA256 digest for GSM: F63B8C602C1DB02F4107D9AF78182D87CD64AEA6521163067B7EB6D5C1B368AF
|
||||
|
||||
[Documentation for GSM](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/gsm.md "Documentation for GSM")
|
||||
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/* 20220307 */
|
||||
GSM: F63B8C602C1DB02F4107D9AF78182D87CD64AEA6521163067B7EB6D5C1B368AF
|
||||
|
||||
/* 20220307 */
|
||||
GSM: 8D730316043A6523A3AF2AA15D2820BB75A46E06307F2B8916D30AC102AEE31D
|
||||
|
||||
/* 20220217 */
|
||||
macroArray: DAEB87654D99965BF2B7A6AB14626B3E617D0ABF526E77725DF89A1AB4C812C2
|
||||
|
||||
/* 20220113 */
|
||||
BasePlus: A60A300E083628C65DD6899E7EF95588916F8F66B6A25B32B3228987B6F74857
|
||||
DFA: 5F89AC6AE628EB27D87FF6A9D72A515FFA3FF6694D04DE0D9811BFFB81444ABB
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
---
|
||||
|
||||
|
||||
# The GSM package [ver. 0.17] <a name="gsm-package"></a> ###############################################
|
||||
# The GSM package [ver. 0.19] <a name="gsm-package"></a> ###############################################
|
||||
|
||||
The **GSM** (a.k.a. *Generate Secure Macros*) package allows
|
||||
to create secured macros stored in SAS Proc FCMP functions.
|
||||
@@ -54,8 +54,33 @@ Recording of presentation with "how it works" description, in Polish, is avaliab
|
||||
```
|
||||
- Share generated `ZIP` file (unzip and run the code).
|
||||
|
||||
*Limitations:*
|
||||
Single macro file cannot be longer than 32760 bytes.
|
||||
**Limitations:**
|
||||
- Single macro file cannot be longer than 32760 bytes.
|
||||
|
||||
- Multiline text variable. Consider the following code text file:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
%macro~test()/SECURE;~#@
|
||||
data~test;~#@
|
||||
a~=~"abc~#@
|
||||
~#@
|
||||
def";~#@
|
||||
put~a~hex20.;~#@
|
||||
run;~#@
|
||||
%mend~test;~#@
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
where `~` symbols the space character,
|
||||
`#` symbols the carriage return (`0D`),
|
||||
and `@` symbols the line feed (`0A`).
|
||||
The code file is scanned and inserted into
|
||||
the `resolve()` function argument in a "byte by byte"
|
||||
fashion hence also the "end of line" characters are included.
|
||||
As the result value of variable `a` will be:
|
||||
|
||||
`a = "abc~#@~#@def"`.
|
||||
|
||||
If you want to use the `GSM` package avoid
|
||||
such "style" of coding in your macros.
|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -69,7 +94,7 @@ Required SAS Components:
|
||||
* SAS package generated by generatePackage, version 20220113 *
|
||||
|
||||
The SHA256 hash digest for package GSM:
|
||||
`3B70D8C31F02CB2B6AC47CC1DB3EC9E462796226CBFF519936AF5EEDB0C46B8F`
|
||||
`F63B8C602C1DB02F4107D9AF78182D87CD64AEA6521163067B7EB6D5C1B368AF`
|
||||
|
||||
|
||||
## >>> `%GSM()` macro: <<< <a name="gsm-macro"></a> #######################
|
||||
@@ -92,7 +117,7 @@ be added to the macro definition. See the example:
|
||||
|
||||
|
||||
As a result a zip file, containing dataset with functions and
|
||||
code to be executed on site, is generated.
|
||||
code to be executed on site, is generated.
|
||||
|
||||
Since encrypted code is stored in a SAS dataset it has
|
||||
no limitation in sharing between operating systems (like catalogs have).
|
||||
@@ -117,6 +142,7 @@ The basic syntax is the following, the `<...>` means optional parameters:
|
||||
<,outpath=>
|
||||
<,encodingRestricted=>
|
||||
<,secret=>
|
||||
<,lineEnd=>
|
||||
)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -125,10 +151,6 @@ The basic syntax is the following, the `<...>` means optional parameters:
|
||||
1. `path` - *Required*, indicates a directory which contains files with macros.
|
||||
Only files with `sas` extension are used.
|
||||
|
||||
* `trim=` - *Optional*, the default value is `0`.
|
||||
If set to `1` then lines of macro code are trimmed.
|
||||
If set to `2` then lines of macro code are stripped.
|
||||
|
||||
* `cmplib=` - *Optional*, the default value is `work.generateMacros`.
|
||||
Names the dataset which will contain generated functions.
|
||||
|
||||
@@ -151,8 +173,20 @@ The basic syntax is the following, the `<...>` means optional parameters:
|
||||
Required to execute the `resolve()` function.
|
||||
User who do not know the value will not be able
|
||||
to run the `_maxro_XX_()` function.
|
||||
---
|
||||
|
||||
* `lineEnd=` - *Optional*, the default value is `0D0A`, indicates which of:
|
||||
line feed, carriage return, or both, or a space be inserted
|
||||
at the end of line in the intermediate code file that is generated.
|
||||
Value has to be hexadecimal code (_NOT_ null),
|
||||
since the value is resolved as `"&lineEnd."x`, so use e.g.
|
||||
`0A` for line feed, `0D` for carriage return,
|
||||
`0D0A` for both, and `20` for space.
|
||||
|
||||
* `trim=` - *Deprecated*, the default value is `0`.
|
||||
*Kept for backward compatibility.*
|
||||
|
||||
|
||||
---
|
||||
|
||||
### Example: ###################################################################
|
||||
|
||||
@@ -197,8 +231,7 @@ run;
|
||||
%GSM(&path., cmplib=work.myMacros)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
## >>> `%GSMpck_makeFCMPcode()` macro: <<< <a name="gsmpck-makefcmpcode-macro"></a> #######################
|
||||
## >>> `%GSMpck_makeFCMPcode()` macro: <<< <a name="GSMpck-makeFCMPcode-macro"></a> #######################
|
||||
|
||||
The `%GSMpck_makeFCMPcode()` macro is an internal macro of
|
||||
the **GSM** (a.k.a. *Generate Secure Macros*) package.
|
||||
@@ -219,11 +252,11 @@ The basic syntax is the following, the `<...>` means optional parameters:
|
||||
%GSMpck_makeFCMPcode(
|
||||
path
|
||||
,number
|
||||
<,trim=0>
|
||||
<,outlib=work.generateMacros.secure>
|
||||
<,source2=>
|
||||
<,fileNameCode=FNC>
|
||||
<,secret=123456789>
|
||||
<,lineEnd=0A>
|
||||
)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -234,9 +267,6 @@ The basic syntax is the following, the `<...>` means optional parameters:
|
||||
|
||||
2. `number` - *Required*, a sequential number.
|
||||
|
||||
* `trim=` - *Optional*, the default value is `0`.
|
||||
If set to `1` then lines of macro code are trimmed.
|
||||
If set to `2` then lines of macro code are stripped.
|
||||
|
||||
* `cmplib=` - *Optional*, the default value is `work.generateMacros`.
|
||||
Names the dataset which will contain generated functions.
|
||||
@@ -253,6 +283,17 @@ The basic syntax is the following, the `<...>` means optional parameters:
|
||||
function. User who do not know the value will not be able
|
||||
to run the `_maxro_XX_()` function.
|
||||
|
||||
* `lineEnd=` - *Optional*, the default value is `0D0A`, indicates which of:
|
||||
line feed, carriage return, or both, or a space be inserted
|
||||
at the end of line in the intermediate code file that is generated.
|
||||
Value has to be hexadecimal code (_NOT_ null),
|
||||
since the value is resolved as `"&lineEnd."x`, so use e.g.
|
||||
`0A` for line feed, `0D` for carriage return,
|
||||
`0D0A` for both, and `20` for space.
|
||||
|
||||
* `trim=` - *Deprecated*, the default value is `0`.
|
||||
*Kept for backward compatibility.*
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
BIN
packages/gsm.zip
BIN
packages/gsm.zip
Binary file not shown.
@@ -10,6 +10,7 @@
|
||||
* [`%do_over3()` macro](#do-over3-macro)
|
||||
* [`%make_do_over()` macro](#make-do-over-macro)
|
||||
* [`%mcHashTable()` macro](#mchashtable-macro)
|
||||
* [`%mcDictionary()` macro](#mcdictionary-macro)
|
||||
* [`%QzipArrays()` macro](#qziparrays-macro)
|
||||
* [`%zipArrays()` macro](#ziparrays-macro)
|
||||
* [`%sortMacroArray()` macro](#sortmacroarray-macro)
|
||||
@@ -18,7 +19,7 @@
|
||||
|
||||
---
|
||||
|
||||
# The macroArray package [ver. 0.9] <a name="macroarray-package"></a> ###############################################
|
||||
# The macroArray package [ver. 1.0] <a name="macroarray-package"></a> ###############################################
|
||||
|
||||
The **macroArray** package implements a macro array facility:
|
||||
- `%array()`,
|
||||
@@ -30,6 +31,7 @@ The **macroArray** package implements a macro array facility:
|
||||
- `%mcHashTable()`,
|
||||
- `%zipArrays()`,
|
||||
- `%sortMacroArray()`,
|
||||
- `%mcDictionary()`,
|
||||
- etc.
|
||||
|
||||
The set of macros, which emulates classic
|
||||
@@ -64,10 +66,11 @@ Package contains:
|
||||
7. macro do_over2
|
||||
8. macro do_over3
|
||||
9. macro make_do_over
|
||||
10. macro mchashtable
|
||||
11. macro sortmacroarray
|
||||
12. macro qziparrays
|
||||
13. macro ziparrays
|
||||
10. macro mcdictionary
|
||||
11. macro mchashtable
|
||||
12. macro qziparrays
|
||||
13. macro sortmacroarray
|
||||
14. macro ziparrays
|
||||
|
||||
Required SAS Components:
|
||||
*Base SAS Software*
|
||||
@@ -75,7 +78,7 @@ Required SAS Components:
|
||||
*SAS package generated by generatePackage, version 20220113.*
|
||||
|
||||
The SHA256 hash digest for package macroArray:
|
||||
`833D747526F4CE83FFD73F9EB3A2A9065401B498DFEC79045A28A42E0E57A8CA`
|
||||
`DAEB87654D99965BF2B7A6AB14626B3E617D0ABF526E77725DF89A1AB4C812C2`
|
||||
|
||||
---
|
||||
# Content description ############################################################################################
|
||||
@@ -1210,7 +1213,7 @@ The basic syntax is the following, the `<...>` means optional parameters:
|
||||
macrovariables named like "`&H._`" are deleted.
|
||||
|
||||
* `HASH=` - *Optional*, indicates which hashing algorithms should be used,
|
||||
available values are `CRC32` or `MD5`, the `CRC32` is the default.
|
||||
available values are `CRC32` or `MD5`, the `CRC32` is the default.
|
||||
|
||||
---
|
||||
|
||||
@@ -1391,7 +1394,7 @@ See examples below to see use cases.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
**EXAMPLE 2.** Populate macro hash table from a dataset.
|
||||
**EXAMPLE 3.** Populate macro hash table from a dataset.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%mcHashTable(CLASS)
|
||||
@@ -1419,7 +1422,7 @@ run;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
**EXAMPLE 3.** Data portion may require quoting and un-quoting..
|
||||
**EXAMPLE 4.** Data portion may require quoting and un-quoting..
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%mcHashTable(CODE)
|
||||
@@ -1436,7 +1439,7 @@ run;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
**EXAMPLE 4.** Longer lists.
|
||||
**EXAMPLE 5.** Longer lists.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%let size = 1000;
|
||||
@@ -1509,7 +1512,7 @@ run;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
**EXAMPLE 5.** Forbidden names.
|
||||
**EXAMPLE 6.** Forbidden names.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%mcHashTable()
|
||||
@@ -1519,7 +1522,7 @@ run;
|
||||
%mcHashTable(ABCDEFGHIJKLMNOP) %* good;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**EXAMPLE 5.** Hashing algorithms.
|
||||
**EXAMPLE 7.** Hashing algorithms.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%mcHashTable(H1,DCL,HASH=MD5)
|
||||
@@ -1528,6 +1531,252 @@ run;
|
||||
|
||||
---
|
||||
|
||||
## >>> `%mcDictionary()` macro: <<< <a name="mcdictionary-macro"></a> #######################
|
||||
|
||||
The `%mcDictionary()` macro provided in the package
|
||||
is designed to facilitate the idea of a "macro dictionary"
|
||||
concept, i.e. *a list of macrovariables with common prefix
|
||||
and suffixes generated as a hash digest* which allows
|
||||
to use values other than integers as indexes.
|
||||
|
||||
The `%mcDictionary()` macro allows to generate other macros
|
||||
which behaves like a dictionary. See examples below.
|
||||
|
||||
The `%mcDictionary()` macro executes like a pure macro code.
|
||||
|
||||
### SYNTAX: ###################################################################
|
||||
|
||||
The basic syntax is the following, the `<...>` means optional parameters:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%mcDictionary(
|
||||
H
|
||||
<,METHOD>
|
||||
)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**Arguments description**:
|
||||
|
||||
1. `H` - *Required*, a dictionary macro name and a declaration/definition,
|
||||
e.g. `mcDictionary(HT)`. It names a macro which is generated by
|
||||
the `%mcDictionary()` macro. Provided name cannot be empty
|
||||
or an underscore (`_`). No longer than *16* characters.
|
||||
|
||||
2. `METHOD` - *Optional*, if empty (or DECLARE or DCL) then the code of
|
||||
a macro dictionary is compiled.
|
||||
If `DELETE` then the macro dictionary named by `H` and all
|
||||
macrovariables named like "`&H._`" are deleted.
|
||||
|
||||
---
|
||||
|
||||
### THE CREATED MACRO `%&H.()`: ####################################################
|
||||
|
||||
The created macro imitates behaviour of a dictionary.
|
||||
|
||||
The basic syntax is the following, the `<...>` means optional parameters:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%&H.(
|
||||
METHOD
|
||||
<,KEY=>
|
||||
<,DATA=>
|
||||
)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**Arguments description**:
|
||||
|
||||
1. `METHOD` - *Required*, indicate what behaviour should be executed.
|
||||
Allowed values are:
|
||||
- `ADD`, adds key and data portion to the macro dictionary,
|
||||
*multiple data portions* are NOT available for one key.
|
||||
- `FIND`, tests if given key exists in the macro dictionary
|
||||
and, if yes, returns data value associated with the key.
|
||||
For multiple data portions see the `data=` parameter.
|
||||
- `CHECK`, returns indicator if the key exists in dictionary.
|
||||
- `DEL`, removes key and data portion from the macro dictionary.
|
||||
- `LIST`, prints out a dictionary to the log.
|
||||
- `CLEAR` removes all data and keys values.
|
||||
|
||||
* `KEY=` - *Optional*, provides key value for `ADD`, `FIND`, `CHECK`
|
||||
and `DEL` methods.
|
||||
Leading and trimming spaces are removed from the value.
|
||||
The `MD5(...)` function is used to generate the hash.
|
||||
Default value is `_`.
|
||||
|
||||
* `DATA=` - *Optional*, provides data value for the `ADD` method.
|
||||
Default value is blank.
|
||||
|
||||
|
||||
When macro is executed and when data are added the following types of
|
||||
*global* macrovariables are created:
|
||||
- `&H._########_K`,
|
||||
- `&H._########_V`,
|
||||
- `&H._KEYSNUM`.
|
||||
|
||||
The `#` represents value generated by the `MD5(...)` function for the given key.
|
||||
|
||||
The first type keeps information about the key.
|
||||
|
||||
The second type keeps information about the value of a given key
|
||||
|
||||
The third type keeps the number of unique values of the key.
|
||||
|
||||
See examples below to see use cases.
|
||||
|
||||
---
|
||||
|
||||
### EXAMPLES AND USECASES: ####################################################
|
||||
|
||||
|
||||
**EXAMPLE 1.** Basic use-case.
|
||||
Creating macro dictionary, macro `Dict` is generated.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%mcDictionary(Dict)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Add elements to the `Dict`.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%Dict(ADD,key=x,data=17)
|
||||
%Dict(ADD,key=y y,data=42)
|
||||
%Dict(ADD,key=z z z,data=303)
|
||||
|
||||
%put _user_;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Add some duplicates for the key x.
|
||||
See macrovariables created.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%Dict(ADD,key=x,data=18)
|
||||
|
||||
%put _user_;
|
||||
|
||||
%Dict(ADD,key=x,data=19)
|
||||
|
||||
%put _user_;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Check for the key `x` and non existing key `t`.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%put ##%Dict(CHECK,key=x)##;
|
||||
%put ##%Dict(CHECK,key=t)##;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Prints data values for various keys.
|
||||
Key `t` does not exist in the macrodictionary.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%put #%Dict(FIND,key=x)#;
|
||||
%put #%Dict(FIND,key=y y)#;
|
||||
%put #%Dict(FIND,key=z z z)#;
|
||||
%put #%Dict(FIND,key=t)#;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
List dictionary content to the log.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%Dict(LIST);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Delete keys.
|
||||
Key `t` does not exist in the macrodictionary.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%put #%Dict(DEL,key=z z z)#;
|
||||
%put _user_;
|
||||
%put #%Dict(DEL,key=t)#;
|
||||
%put _user_;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Clear and delete macro dictionary `Dict`.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%Dict(CLEAR)
|
||||
%put _user_;
|
||||
|
||||
%mcDictionary(Dict,DELETE)
|
||||
%put _user_;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
**EXAMPLE 2.** Populate macro dictionary from a dataset.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%mcDictionary(CLASS)
|
||||
%let t = %sysfunc(datetime());
|
||||
data _null_;
|
||||
set sashelp.class;
|
||||
call execute('%CLASS(ADD,key=' !! name !! ',data=' !! age !! ')');
|
||||
run;
|
||||
%put t = %sysevalf(%sysfunc(datetime()) - &t.);
|
||||
%put _user_;
|
||||
%CLASS(CLEAR)
|
||||
|
||||
|
||||
%mcDictionary(CARS)
|
||||
%let t = %sysfunc(datetime());
|
||||
data _null_;
|
||||
set sashelp.cars;
|
||||
call execute('%CARS(ADD,key=' !! catx("|",make,model,type) !! ',data=' !! MPG_CITY !! ')');
|
||||
run;
|
||||
%put t = %sysevalf(%sysfunc(datetime()) - &t.);
|
||||
%put &=CARS_KEYSNUM.;
|
||||
%CARS(LIST);
|
||||
%CARS(CLEAR)
|
||||
%put &=CARS_KEYSNUM.;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
**EXAMPLE 3.** Data portion may require quoting and un-quoting..
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%mcDictionary(CODE)
|
||||
%CODE(CLEAR)
|
||||
%CODE(ADD,key=data, data=%str(data test; x = 42; run;))
|
||||
%CODE(ADD,key=proc, data=%str(proc print; run;))
|
||||
%CODE(ADD,key=macro,data=%nrstr(%put *****;))
|
||||
|
||||
%CODE(FIND,key=data)
|
||||
%CODE(FIND,key=proc)
|
||||
%unquote(%CODE(FIND,key=macro))
|
||||
|
||||
%CODE(LIST);
|
||||
|
||||
%mcDictionary(CODE,DELETE)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
**EXAMPLE 4.** Longer lists.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%let size = 1000;
|
||||
|
||||
%mcDictionary(AAA)
|
||||
|
||||
%let t = %sysfunc(datetime());
|
||||
data _null_;
|
||||
do i = 1 to &size.;
|
||||
call execute(cats('%AAA(ADD,key=A', i, ',data=', i, ')'));
|
||||
end;
|
||||
run;
|
||||
%put t = %sysevalf(%sysfunc(datetime()) - &t.);
|
||||
%put &=AAA_KEYSNUM;
|
||||
%AAA(CLEAR)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
**EXAMPLE 5.** Forbidden names.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||
%mcDictionary()
|
||||
%mcDictionary(_)
|
||||
|
||||
%mcDictionary(ABCDEFGHIJKLMNOPQ) %* bad;
|
||||
%mcDictionary(ABCDEFGHIJKLMNOP) %* good;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
---
|
||||
|
||||
## >>> `%QzipArrays()` macro: <<< <a name="qziparrays-macro"></a> #######################
|
||||
|
||||
The zipArrays() and QzipArrays() macros
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user