Rebol3 Code Examplex
XXXX redacted
Remove or mask sensitive text from content.
Rebol [
title: "Rosetta code: XXXX redacted"
file: %XXXX_redacted.r3
url: https://rosettacode.org/wiki/XXXX_redacted
needs: 3.21.0 ;; Unicode
]
radect-text: function/with [
mode [any-word! string! ref!] "Any: wsn win psn pin pso pio"
word [string!] "Word to hide"
text [string! file! url!]
][
unless string? text [text: read/string text]
mode: form mode
rplc: append/dup clear "" #"X" length? word ;; replacement: "XXX" same length as word
case: mode/2 = #"s" ;; s = case-sensitive, n = case-insensitive
either mode/3 = #"o" [
;; Overkill: redact the entire token containing the match
rule: [
to word s: (
unless head? s [s: find/reverse/tail s o-chars] ;; back up to token start
e: any [find s o-chars tail s] ;; scan forward to token end
rplc: append/dup clear "" #"X" len: (index? e) - (index? s) ;; fit XXX to token length
e: change/part s rplc e
) :e
]
][ ;; Whole / partial match
rule: either/only mode/1 = #"w" [
ahead [word w-chars] change word rplc | thru delimit ;; whole: match word at boundary
][ change word rplc | skip] ;; partial: match anywhere
]
parse/:case text [any rule]
text
][ ;; Static charset definitions (shared across all calls)
w-chars: charset { ^-^/.,;:?} ;; chars that may follow a whole word
delimit: charset "- .;:?^/^"[](){}" ;; token delimiters for whole-word skipping
o-chars: charset " .;:?^/^"[](){}" ;; token boundaries for overkill mode
]
;; Test cases:
text: {Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so tom.}
foreach word ["Tom" "tom"][
print ["Redact" as-green word ":"]
foreach mode [wsn win psn pin pso pio][ ;; w/p=whole/partial, s/n=case, o=overkill
print [mode radect-text :mode :word copy :text]
]
]
print ["Redact" "👨" ":"]
probe radect-text 'w "👨" "🧑 👨 🧔 👨👩👦" ;; sanity-check Unicode handling
Output:
Redact Tom :
wsn XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so tom.
win XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX.
psn XXX? XXXs bottom tomato is in his stomach while playing the "XXX-tom" brand tom-toms. That's so tom.
pin XXX? XXXs botXXX XXXato is in his sXXXach while playing the "XXX-XXX" brand XXX-XXXs. That's so XXX.
pso XXX? XXXX bottom tomato is in his stomach while playing the "XXXXXXX" brand tom-toms. That's so tom.
pio XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX.
Redact tom :
wsn Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX.
win XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX.
psn Tom? Toms botXXX XXXato is in his sXXXach while playing the "Tom-XXX" brand XXX-XXXs. That's so XXX.
pin XXX? XXXs botXXX XXXato is in his sXXXach while playing the "XXX-XXX" brand XXX-XXXs. That's so XXX.
pso Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX.
pio XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX.
Redact 👨 :
"🧑 X 🧔 👨👩👦"