- Clean a customer line before import
- SQL table and API names from form labels
- Parse an API access log line
- Encode a payment callback and check it
- Colors, permissions and character codes
- Encrypt, decrypt and sign a secret
- Match a typed product name to the catalog
- Mail merge: fill a template from JSON data
- Mask personal data before writing a log line
- Write and read a fixed width bank transfer file
Clean a customer line before import
A customer file arrives with extra spaces, mixed case, accents and an empty note. The script trims and normalises each field, builds the initials, a padded customer code and a slug, and outputs a clean CSV line.
#1. A raw line of a customer file with spaces, accents and mixed case; -> "[name]" " jean-PAUL dupont-lefèvre "; -> "[mail]" " ÉLODIE.Martin@Mail.COM "; -> "[city]" " Saint-Denis "; -> "[country]" " FRANCE "; -> "[code]" " 042 "; -> "[note]" ""; #2. Clean every field; -> "[name]" (string capitalize_words (string itrim (string lrtrim [name]))); -> "[mail]" (string lcase (string unaccent (string trim [mail]))); -> "[city]" (string upper (string rtrim (string ltrim [city]))); -> "[code]" (concat "C" (string lpad (string lrtrim [code]) "0" 6)); -> "[initials]" (concat (string ucase (string first_letter [name])) (string upper (string first_letter (string mid [name] (+ (string instr [name] " ") 1))))); #3. Optional field, slug and CSV export; -> "[note]" (string empty_if_null (string null_if_empty [note])); concat (string csv_value [code] ";" "\"") ";" (string csv_value [name] ";" "\"") ";" [initials] ";" [mail] ";" [city] ";" (string first_letter_upper (string lower (string trim [country]))) ";" (string slugify [name]) ";" (string zero [note]) ";blank=" (string is_blank [note]) ";" (string lrtrim0 "00042")
C000042;Jean-Paul Dupont-Lefèvre;JD;elodie.martin@mail.com;SAINT-DENIS;France;jean-paul-dupont-lefevre;0;blank=1;42
- Detect duplicates with
string levenshtein_distanceon the cleaned names - Check the cleaned mail with
type is_emailbefore the insert
SQL table and API names from form labels
A form has French labels with accents and spaces. The script turns them into snake_case column names aligned with padding, SQL comments with escaped quotes, a camelCase JSON field, a kebab-case route and an HTML view of the MQL snippet for the wiki.
#1. Business labels of a form become a SQL table; -> "[labels]" "Date de naissance,Montant TTC,Numéro client,Commentaire libre du vendeur"; -> "[ddl]" (concat "CREATE TABLE " (string snake_case "Fiche Client") " (" [_n_]); -> "[i]" 0; #2. One column per label: snake_case name, padded for alignment, SQL comment; for (-> "[i]" 1) (<= [i] 4) (++ "[i]") { -> "[lab]" (atom get [labels] [i] ","); -> "[col]" (string snake_case (string unaccent [lab])); -> "[ddl]" (concat [ddl] (string rpad [col] " " 30) "VARCHAR(100) COMMENT " (string txt2 (string truncate [lab] 20)) "," [_n_]); }; -> "[ddl]" (concat (string substring [ddl] 0 (- (string length [ddl]) 2)) [_n_] ");"); #3. Same names for the JSON API and the URL routes, plus the snippet in HTML for the wiki; concat (string indent [ddl] 2) [_n_] (string repeat "-" 40) [_n_] "json: " (string camel_case (string unaccent "Montant TTC")) ", route: /" (string kebab_case (string camel_case (string unaccent "Numéro client"))) [_n_] "sql literals: " (string to_string "O\"Neil") " " (string txt "l'été") [_n_] "trimmed: " (string sublrchar "[ok]" 1) (string space 2) (string replace "v1.2.3" "." "_") [_n_] (string del_char_before_each_line (concat "-- col1" [_n_] "-- col2") 3) [_n_] "doc html: " (string mql_to_html (mql {string snake_case "Fiche Client";}))
CREATE TABLE fiche_client ( date_de_naissance VARCHAR(100) COMMENT 'Date de naissance', montant_ttc VARCHAR(100) COMMENT 'Montant TTC', numero_client VARCHAR(100) COMMENT 'Numéro client', commentaire_libre_du_vendeur VARCHAR(100) COMMENT 'Commentaire libre...' ); ---------------------------------------- json: montantTtc, route: /numero-client sql literals: 'O"Neil' 'l\'été' trimmed: ok v1_2_3 col1 col2 doc html: <span style='color:#00baff'>string</span> <span style='color:#00baff'>snake_case</span> <span style='color:#fff'>"Fiche Client"</span>;
- Pick the column types with the
type is_*checks on sample data string truncatekeeps comments under the database limit
Parse an API access log line
An access log line holds a date, a level, a route with an order id, a status and a duration. The script extracts the fields with regex groups, rewrites the date, reads the variables of an error message with a pattern and classifies the line with the match functions.
#1. One line of an API access log; -> "[l]" "2026-11-01 08:15:42 ERROR [api] GET /orders/A-1234?user=jim 500 812ms"; #2. Extract the fields with regex groups; -> "[code]" (string regexp_extract [l] " ([0-9]{3}) [0-9]+ms$" 1); -> "[ms]" (string regexp_extract [l] "([0-9]+)ms$" 1); -> "[order]" (string regexp_extract [l] "/orders/([A-Z]-[0-9]+)" 1); -> "[day]" (string regexp_replace (string left [l] 10) "([0-9]+)-([0-9]+)-([0-9]+)" "$3/$2/$1"); -> "[msg]" "Timeout in module payment at line 42"; -> "[vars]" (string replace (string replace (string get_variable [msg] "[1] in module [2] at line [3]") [_n_] "") " " ""); #3. Classify the line; -> "[words]" (string split [l] " " -1); concat "{\"day\": \"" [day] "\", \"order\": \"" [order] "\", \"status\": " [code] ", \"ms\": " [ms] ", \"message_vars\": " [vars] ", \"words\": " [words] ", \"numbers\": " (string regexp_count [l] "[0-9]+") ", \"slashes\": " (string count [l] "/") ", \"is_error\": " (string contains [l] "ERROR") ", \"has_user\": " (string contains_ignore_case [l] "USER=") ", \"api_tag\": " (string regexp [l] ".*\[api\].*") ", \"not_debug\": " (string not_regexp [l] ".*DEBUG.*") ", \"like_get\": " (string like [l] ".* GET .*") ", \"not_like_post\": " (string not_like [l] ".* POST .*") ", \"matches\": " (string matches [l] ".*orders.*") ", \"is_matches_regex\": " (type is_matches_regex [l] ".*812ms") ", \"starts_2026\": " (string starts_with [l] "2026") ", \"starts_digit\": " (string starts_with_or [l] "0123456789") ", \"ends_ms\": " (string ends_with [l] "ms") ", \"level_is_error\": " (string equals_ignore_case (string split_mql [l] 2) "error") ", \"parts\": " (string split_sentence "GET /orders/A-1234?user=jim" "/?=") "}"
{"day": "01/11/2026", "order": "A-1234", "status": 500, "ms": 812, "message_vars": ["Timeout","payment","42"], "words": ["2026-11-01","08:15:42","ERROR","[api]","GET","\/orders\/A-1234?user=jim","500","812ms"], "numbers": 9, "slashes": 2, "is_error": 1, "has_user": 1, "api_tag": 1, "not_debug": 1, "like_get": 1, "not_like_post": 1, "matches": 1, "is_matches_regex": 1, "starts_2026": 1, "starts_digit": 1, "ends_ms": 1, "level_is_error": 1, "parts": ["GET","orders","A-1234","user","jim"]}- Run it on each line read with
file reader_get_lineand count the 500 errors per hour string regexp_countgives a quick density of numbers or ids per line
Encode a payment callback and check it
A payment callback carries a French label with & and accents, a Basic auth header and an HTML note. The script URL-encodes and Base64-encodes them, escapes for HTML and JSON, decodes everything back and measures the label.
#1. A payment callback with a French label and an HTML note; -> "[label]" "Commande n°42 & frais d'été"; -> "[q]" (concat "label=" (string url_encode [label]) "&amount=19.90"); -> "[auth]" (concat "Basic " (string encode_b64 "shop:test-key")); #2. Safe versions for HTML and JSON outputs; -> "[html]" (string html_escape "<b>Tom & Jerry's</b>"); -> "[js]" (string json_escape (concat "line1" [_n_] "say \"hi\"")); #3. Decode everything back and measure the label; concat "{\"query\": \"" [q] "\", \"auth\": \"" [auth] "\", \"auth_back\": \"" (string decode_b64 (string mid [auth] 6)) "\", \"label_back\": \"" (string url_decode (string mid [q] 6 (string instr [q] "&a"))) "\", \"html\": \"" [html] "\", \"html_back\": \"" (string html_unescape "café & thé") "\", \"json_value\": \"" [js] "\", \"utf8_to_latin1\": \"" (string encode "abc" "UTF-8" "ISO-8859-1") "\", \"length\": " (string length [label]) ", \"char_length\": " (string char_length [label]) ", \"bit_length\": " (string bit_length [label]) "}"
{"query": "label=Commande%20n%C2%B042%20%26%20frais%20d%27%C3%A9t%C3%A9&amount=19.90", "auth": "Basic c2hvcDp0ZXN0LWtleQ==", "auth_back": "shop:test-key", "label_back": "Commande n°42 & frais d'été", "html": "<b>Tom & Jerry's</b>", "html_back": "café & thé", "json_value": "line1\nsay \"hi\"", "utf8_to_latin1": "abc", "length": 27, "char_length": 27, "bit_length": 216}- Sign the query with
string hmac_sha256so the shop can check it string bit_lengthtells the size in bits of the payload,string lengththe number of characters
Colors, permissions and character codes
A front developer needs the RGB values of the brand color #FFB547 and a sysadmin wants to read the 755 permission in decimal and in bits. The script converts between hexadecimal, octal, binary and characters.
#1. A web color and a Unix permission to decode; -> "[color]" "FFB547"; -> "[r]" (string hex_to_int (string left [color] 2)); -> "[g]" (string unhex (string mid [color] 2 4)); -> "[b]" (string hex_to_int (string right [color] 2)); -> "[perm]" (string oct_to_int "755"); #2. Characters and their codes; -> "[c]" "é"; concat "{\"rgb\": [" [r] ", " [g] ", " [b] "], \"back_to_hex\": \"" (string upper (concat (string hex [r]) (string int_to_hex [g]) (string int_to_hex [b]))) "\", \"perm_755_decimal\": " [perm] ", \"perm_bits\": \"" (string bin [perm]) "\", \"perm_octal\": \"" (string oct [perm]) "|" (string int_to_oct 420) "\", \"ascii_A\": " (string ascii "A") ", \"code_e_acute\": " (string char_to_int [c]) ", \"char_77\": \"" (string char 77) (string int_to_char 68) (string int_to_char 66) "\", \"hex_of_MDB\": \"" (string str_to_hex "MDB") "\", \"hex_41_to_str\": \"" (string hex_to_str "41") "\"}"
{"rgb": [255, 181, 71], "back_to_hex": "FFB547", "perm_755_decimal": 493, "perm_bits": "111101101", "perm_octal": "755|644", "ascii_A": 65, "code_e_acute": 233, "char_77": "MDB", "hex_of_MDB": "4d4442", "hex_41_to_str": "A"}- Lighten a color by adding 20 to each channel before
string int_to_hex string str_to_hexhelps to spot invisible characters in an imported field
Encrypt, decrypt and sign a secret
An API token must be stored encrypted and its origin proven. The script generates RSA and signature key pairs, encrypts the token with RSA, DES, Blowfish and PBE, decrypts each one, signs it and checks that a tampered token fails the signature.
#1. Key pairs for RSA and for signatures, kept as JSON in memory; json load "rx_rsa" (string encode_rsa_generate_keypair "2048"); json load "rx_sig" (string encode_sign_generate_keypair "2048"); -> "[secret]" (concat "token-" (string uuid)); #2. Encrypt with RSA, DES, Blowfish and PBE, then decrypt; -> "[rsa]" (string encode_rsa [secret] (json select "rx_rsa" "/publicKey") (json select "rx_rsa" "/privateKey")); -> "[des_key]" (string encode_des_generate_key "56"); -> "[des]" (string encode_des [secret] [des_key]); -> "[bf]" (string encode_blowfish [secret] "vault-key-2026"); -> "[pbe]" (string encode_pbe [secret] "master-password"); #3. Sign the secret and check the signature; -> "[sig]" (string encode_sign [secret] (json select "rx_sig" "/privateKey")); -> "[ok]" (concat "{\"rsa_ok\": " (string equals_ignore_case (string decode_rsa [rsa] (json select "rx_rsa" "/privateKey")) [secret]) ", \"des_ok\": " (string equals_ignore_case (string decode_des [des] [des_key]) [secret]) ", \"blowfish_ok\": " (string equals_ignore_case (string decode_blowfish [bf] "vault-key-2026") [secret]) ", \"pbe_ok\": " (string equals_ignore_case (string decode_pbe [pbe] "master-password") [secret]) ", \"signature_ok\": " (string decode_sign_verify [secret] [sig] (json select "rx_sig" "/publicKey")) ", \"tampered_ok\": " (string decode_sign_verify (concat [secret] "x") [sig] (json select "rx_sig" "/publicKey")) ", \"random_salt_length\": " (string length (string generate_random_str 16)) "}"); json unload "rx_rsa"; json unload "rx_sig"; [ok]
{"rsa_ok": 1, "des_ok": 1, "blowfish_ok": 1, "pbe_ok": 1, "signature_ok": 1, "tampered_ok": 0, "random_salt_length": 16}- Keep the private keys out of the code: read them from a parameter
- For passwords, prefer
string bcrypt_hash, which cannot be decrypted
Match a typed product name to the catalog
A user types a product name with small differences from the catalog. The script measures the edit distance and the sentence distance, picks the best catalog label, then cuts the SKU into family and variant and checks its parts.
#1. A product name typed by a user, to match against the catalog; -> "[typed]" "Ecran 27 pouces IPS"; -> "[ref]" "SKU-EC27-IPS"; #2. Edit distance and sentence distance to the catalog labels; -> "[lev]" (string levenshtein_distance (string lower "Ecran 27p IPS") (string lower "ecran 27 ips")); -> "[sd]" (string sentence_distance 40 70 [typed] "Ecran IPS 27 pouces noir"); -> "[best]" (string sentences_distance 40 70 [typed] "{\"1\": {\"i\": \"Clavier sans fil\", \"o\": \"SKU-KB01\"}, \"2\": {\"i\": \"Ecran IPS 27 pouces\", \"o\": \"SKU-EC27-IPS\"}, \"3\": {\"i\": \"Ecran 24 pouces TN\", \"o\": \"SKU-EC24-TN\"}}"); -> "[sku]" (json load select "rx_best" [best] "/best_predict"); json unload "rx_best"; #3. Cut the SKU into its parts; -> "[p1]" (string instr [ref] "-"); -> "[p2]" (string locate [ref] "-" (+ [p1] 1)); concat "{\"levenshtein\": " [lev] ", \"sentence_distance\": " [sd] ", \"best_sku\": \"" [sku] "\", \"family\": \"" (string substr [ref] (+ [p1] 1) [p2]) "\", \"variant\": \"" (string substring [ref] (+ [p2] 1)) "\", \"prefix\": \"" (string left [ref] 3) "\", \"suffix\": \"" (string right [ref] 3) "\", \"dash_pos\": [" (string position [ref] "-") ", " (string strpos [ref] "-" 4) "], \"sorted\": " (string order "[\"SKU-EC27-IPS\", \"SKU-EC24-TN\", \"SKU-KB01\"]") ", \"cmp\": " (string strcmp "SKU-EC24-TN" "SKU-EC27-IPS") ", \"reversed\": \"" (string reverse [ref]) "\", \"grouped\": \"" (string repeat_insert_str "4111111111111111" " " 4) "\", \"letters_only\": " (string is_letter "Ecran") ", \"alnum\": " (string is_alpha_num "EC27") ", \"alnum_uds\": " (string is_alpha_num_uds "EC_27") ", \"digits\": " (string is_number_char "27") "}"
{"levenshtein": 1, "sentence_distance": 200.0, "best_sku": "SKU-EC27-IPS", "family": "EC27", "variant": "IPS", "prefix": "SKU", "suffix": "IPS", "dash_pos": [3, 8], "sorted": ["SKU-EC24-TN","SKU-EC27-IPS","SKU-KB01"], "cmp": -3, "reversed": "SPI-72CE-UKS", "grouped": "4111 1111 1111 1111 ", "letters_only": 1, "alnum": 1, "alnum_uds": 1, "digits": 1}- Raise the activation percent of
string sentences_distanceto be stricter - Sort candidate SKUs with
string orderbefore showing them
Mail merge: fill a template from JSON data
Fill the {{placeholders}} of a shipping mail with the data of an order: values are first formatted the French way (capital first letter, 1 249,50 with a thousands space, dd/MM/yyyy), then merged with a loop on the JSON fields. Unresolved placeholders are counted and removed, and the text is produced in plain and in safe HTML.
#1. A mail template with placeholders and the data of one customer; -> "[tpl]" "Hello {{first_name}},|your order {{order}} of {{amount}} EUR ships on {{ship_date}}.|Track it: {{track_url}}|{{missing}}"; json load "rx_p4l_data" "{\"first_name\": \"élodie\", \"order\": \"A-1042\", \"amount\": 1249.5, \"ship_date\": \"2026-11-03\", \"track_url\": \"https://track.example.com/?id=A-1042&lang=fr\"}"; #2. Format the values the French way before the merge: 1 249,50 and dd/MM/yyyy; json uobject "rx_p4l_data" "/" "first_name" (string first_letter_upper (json select "rx_p4l_data" "/first_name")) STR; -> "[amt]" (json select "rx_p4l_data" "/amount"); -> "[int]" (string trim (string reverse (string repeat_insert_str (string reverse (math trunc [amt])) " " 3))); -> "[cents]" (string lpad (math round (* (math frac_part [amt]) 100) 0) "0" 2); json uobject "rx_p4l_data" "/" "amount" (concat [int] "," [cents]) STR; json uobject "rx_p4l_data" "/" "ship_date" (date format (json select "rx_p4l_data" "/ship_date") "yyyy-MM-dd" "dd/MM/yyyy") STR; #3. Replace each placeholder by its value; -> "[text]" [tpl]; json parse_obj "rx_p4l_data" "/" "[k]" "[v]" { -> "[text]" (string replace [text] (concat "{{" [k] "}}") [v]); }; json unload "rx_p4l_data"; #4. Placeholders without data are listed then removed; -> "[left]" (string regexp_count [text] "\{\{[a-z_]+\}\}"); -> "[name]" (string regexp_extract [text] "\{\{([a-z_]+)\}\}" 1); -> "[text]" (string regexp_replace [text] "\|?\{\{[a-z_]+\}\}" ""); #5. Plain text for the SMS, HTML for the mail; -> "[plain]" (string replace [text] "|" [_n_]); -> "[html]" (concat "<p>" (string replace (string html_escape [text]) "|" "<br>") "</p>"); concat [plain] [_n_] "--- " (string length [plain]) " chars, unresolved: " [left] " (" [name] ")" [_n_] [html];
Hello Élodie, your order A-1042 of 1 249,50 EUR ships on 03/11/2026. Track it: https://track.example.com/?id=A-1042&lang=fr --- 123 chars, unresolved: 1 (missing) <p>Hello Élodie,<br>your order A-1042 of 1 249,50 EUR ships on 03/11/2026.<br>Track it: https://track.example.com/?id=A-1042&lang=fr</p>
- Keep the templates in a node or in
translate setkeys to have one version per language. - Send the HTML with
mail sendonce the text has no{{left.
Mask personal data before writing a log line
A support log line contains an e-mail, a card number, an IBAN, a phone, an IP and an API token. The script masks each one with the rule of its kind (PCI DSS keeps the last 4 digits of a card), redacts the secret and replaces the user by a stable salted pseudonym.
#1. A support log line full of personal data, before it goes to the shared logs; -> "[line]" "2026-11-01 09:12 user=marie.dupont@gmail.com card=4970 1012 3456 7890 iban=FR7630006000011234567890189 tel=+33 6 12 34 56 78 ip=192.168.1.42 token=sk_live_9f8e7d6c5b4a"; #2. E-mail: keep the first letter and the domain; -> "[mail]" (string regexp_extract [line] "user=([^ ]+)" 1); -> "[mail_m]" (concat (string left [mail] 1) (string repeat "*" (- (string instr [mail] "@") 1)) (string substring [mail] (string instr [mail] "@"))); #3. Card: only the last 4 digits, the PCI DSS rule; -> "[card]" (string regexp_replace (string regexp_extract [line] "card=([0-9 ]{19})" 1) " " ""); -> "[card_m]" (string repeat_insert_str (concat (string repeat "*" 12) (string right [card] 4)) " " 4); #4. IBAN, phone, IP and secret with regular expressions; -> "[out]" (string replace [line] [mail] [mail_m]); -> "[out]" (string regexp_replace [out] "card=[0-9 ]{19}" (concat "card=" (string trim [card_m]))); -> "[out]" (string regexp_replace [out] "(FR[0-9]{2})[0-9]{19}([0-9]{4})" "$1*******************$2"); -> "[out]" (string regexp_replace [out] "(\+33 [0-9]) [0-9]{2} [0-9]{2} [0-9]{2} ([0-9]{2})" "$1 ** ** ** $2"); -> "[out]" (string regexp_replace [out] "ip=([0-9]+\.[0-9]+)\.[0-9]+\.[0-9]+" "ip=$1.x.x"); -> "[out]" (string regexp_replace [out] "token=[A-Za-z0-9_]+" "token=[REDACTED]"); #5. A stable pseudonym lets support follow the same user without the e-mail; -> "[pseudo]" (concat "usr_" (string left (string sha_256 (concat "salt-2026:" (string lower [mail]))) 10)); concat [out] [_n_] "pseudonym: " [pseudo] [_n_] "digits left in clear: " (string regexp_count [out] "[0-9]") " of " (string regexp_count [line] "[0-9]") ", e-mail kept: " (string contains [out] [mail]) ", same length: " (== (string length (string trim [card_m])) 19);
2026-11-01 09:12 user=m***********@gmail.com card=**** **** **** 7890 iban=FR76*******************0189 tel=+33 6 ** ** ** 78 ip=192.168.x.x token=[REDACTED] pseudonym: usr_a8895a160d digits left in clear: 33 of 79, e-mail kept: 0, same length: 1
- Put the masking in an
exescript and include it in everylog writeof your services. - Store the salt in a private parameter (
parameter set_private) rather than in the code.
Write and read a fixed width bank transfer file
Build a fixed width transfer file for a bank: detail records with a sequence number, a name in upper case without accents cut or padded to 24 characters, an 11-digit account and the amount in cents on 12 digits, then a trailer with the count and the control total, and an MD5 checksum. The bank side reads the fields back by position and checks the total.
#1. Transfers to send to the bank in a fixed width file: type 2, name 24, account 11, amount 12 in cents; -> "[rows]" "Hélène Côté-Dubois;00012345678;1250.5|Jean Martin;98765432100;89.99|Société Réunionnaise des Eaux Tropicales;55511122233;14000"; -> "[file]" ""; -> "[total]" 0; for (-> "[i]" 1) (<= [i] (atom size [rows] "|")) (++ "[i]") { -> "[r]" (atom get [rows] [i] "|"); #2. Banks want upper case without accents, cut or padded to the width; -> "[name]" (string rpad (string left (string upper (string unaccent (atom get [r] 1 ";"))) 24) " " 24); -> "[cents]" (math round (* (atom get [r] 3 ";") 100) 0); -> "[total]" (+ [total] [cents]); -> "[file]" (concat [file] "02" (string lpad [i] "0" 6) [name] (atom get [r] 2 ";") (string lpad [cents] "0" 12) [_n_]); }; #3. Trailer record with the count and the control total, then a checksum; -> "[file]" (concat [file] "09" (string lpad (atom size [rows] "|") "0" 6) (string space 35) (string lpad [total] "0" 12)); -> "[md5]" (string md5 [file]); #4. The bank side: read the fields back by position and check the total; -> "[check]" 0; -> "[parsed]" ""; for (-> "[j]" 1) (< [j] (atom size [file] [_n_])) (++ "[j]") { -> "[l]" (atom get [file] [j] [_n_]); -> "[amount]" (/ (string substring [l] 43 55) 100); -> "[check]" (+ [check] (string substring [l] 43 55)); -> "[parsed]" (concat [parsed] (string rtrim (string substring [l] 8 32)) " | " (string substring [l] 32 43) " | " [amount] [_n_]); }; -> "[trailer]" (atom get_last [file] [_n_]); concat [file] [_n_] "--- every line " (string length [trailer]) " chars, md5 " [md5] [_n_] [parsed] "control total: " (string lrtrim0 (string right [trailer] 12)) " cents, recomputed: " [check] ", equal: " (== [check] (string right [trailer] 12));
02000001HELENE COTE-DUBOIS 00012345678000000125050 02000002JEAN MARTIN 98765432100000000008999 02000003SOCIETE REUNIONNAISE DES55511122233000001400000 09000003 000001534049 --- every line 55 chars, md5 b9294a861c1315974513bbdc5990d59e HELENE COTE-DUBOIS | 00012345678 | 1250.5 JEAN MARTIN | 98765432100 | 89.99 SOCIETE REUNIONNAISE DES | 55511122233 | 14000 control total: 1534049 cents, recomputed: 1534049, equal: 1
- Write the file with
file create "tmp/..."and send it withsftp putin a job. - Real bank formats (CFONB 160, AFB 120) only change the widths and the record types.
