XXXX redacted: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
 
(8 intermediate revisions by 6 users not shown)
Line 62:
{{Template:Strings}}
<br><br>
 
=={{header|Ada}}==
<syntaxhighlight lang="ada">
-- Redact text
-- J. Carter 2023 Apr
 
with Ada.Characters.Handling;
with Ada.Containers.Vectors;
with Ada.Strings.Fixed;
with Ada.Strings.Unbounded;
with Ada.Text_IO;
 
procedure Redact is
use Ada.Strings.Unbounded;
 
package Field_Lists is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Unbounded_String);
 
function Parsed (Line : String) return Field_Lists.Vector;
-- Presumes that Line consists of fields speparated by 1 or more spaces (' ')
-- Returns a list of the parsed fields
function Redact (Word : in Field_Lists.Vector;
Pattern : in String;
Whole_Word : in Boolean;
Case_Sensitive : in Boolean;
Overkill : in Boolean)
return String;
-- Redacts the words or parts of words in Word containing Pattern
-- If Whole_Word, the entire word must match Pattern, and Overkill is ignored
-- Case_Sensitive determines whether or not the match is case sensitive
-- Overkill means the entire word is redacted even if only a part matches
 
function Parsed (Line : String) return Field_Lists.Vector is
Result : Field_Lists.Vector;
Start : Natural := Line'First;
Stop : Natural;
begin -- Parsed
All_Fields : loop
Start := Ada.Strings.Fixed.Index_Non_Blank (Line (Start .. Line'Last) );
 
exit All_Fields when Start = 0;
 
Stop := Ada.Strings.Fixed.Index (Line (Start .. Line'Last), " ");
if Stop = 0 then
Stop := Line'Last + 1;
end if;
Result.Append (New_Item => To_Unbounded_String (Line (Start .. Stop - 1) ) );
Start := Stop + 1;
end loop All_Fields;
 
return Result;
end Parsed;
function Redact (Word : in Field_Lists.Vector;
Pattern : in String;
Whole_Word : in Boolean;
Case_Sensitive : in Boolean;
Overkill : in Boolean)
return String is
subtype Lower is Character range 'a' .. 'z';
subtype Upper is Character range 'A' .. 'Z';
Pat : constant String := (if Case_Sensitive then Pattern else Ada.Characters.Handling.To_Lower (Pattern) );
Result : Unbounded_String;
Start : Positive; -- Start of a word, ignoring initial punctuation
Stop : Positive; -- End of a word, ignoring terminal punctuation
First : Natural; -- Start of partial match
Last : Natural; -- End of partial match
begin -- Redact
All_Words : for I in 1 .. Word.Last_Index loop
One_Word : declare
Raw : String := To_String (Word.Element (I) );
Woid : String := (if Case_Sensitive then Raw else Ada.Characters.Handling.To_Lower (Raw) );
begin -- One_Word
Start := Woid'First; -- Ignore initial punctuation
Find_Start : loop
exit Find_Start when Woid (Start) in Lower | Upper;
Start := Start + 1;
end loop Find_Start;
Stop := Woid'Last; -- Ignore terminal punctuation
Find_Stop : loop
exit Find_Stop when Woid (Stop) in Lower | Upper;
Stop := Stop - 1;
end loop Find_Stop;
if Whole_Word then
if Woid (Start .. Stop) = Pat then
Raw (Start .. Stop) := (Start .. Stop => 'X');
end if;
else
Last := Start - 1;
All_Matches : loop -- Multiple matches are possible within a single word
First := Ada.Strings.Fixed.Index (Woid (Last + 1 .. Stop), Pat);
exit All_Matches when First = 0;
Last := (if Overkill then Stop else First + Pattern'Length - 1);
if Overkill then
First := Start;
end if;
Raw (First .. Last) := (First .. Last => 'X');
end loop All_Matches;
end if;
Append (Source => Result, New_Item => Raw & (if I = Word.Last_Index then "" else " ") );
end One_Word;
end loop All_Words;
return To_String (Result);
end Redact;
subtype Pattern_String is String (1 .. 3);
type Pattern_List is array (1 .. 2) of Pattern_String;
Pattern : constant Pattern_List := ("Tom", "tom");
Line : constant String := "Tom? Toms bottom tomato is in his stomach while playing the " & '"' & "Tom-tom" & '"' &
" brand tom-toms. That's so tom.";
Word : constant Field_Lists.Vector := Parsed (Line);
begin -- Redact
All_Patterns : for Pat of Pattern loop
Ada.Text_IO.Put_Line (Item => "Pattern: " & Pat);
Wholeness : for Whole in Boolean loop
Sensitivity : for Sense in Boolean loop
if Whole then
Ada.Text_IO.Put_Line (Item => 'W' & (if Sense then 'S' else 'I') & "N: " & Redact (Word, Pat, Whole, Sense, False) );
else
Overkill : for Over in Boolean loop
Ada.Text_IO.Put_Line (Item => (if Whole then 'W' else 'P') &
(if Sense then 'S' else 'I') &
(if Over then 'O' else 'N') & ": " &
Redact (Word, Pat, Whole, Sense, Over) );
end loop Overkill;
end if;
end loop Sensitivity;
end loop Wholeness;
end loop All_Patterns;
end Redact;
</syntaxhighlight>
 
{{out}}
<pre>
Pattern: Tom
PIN: XXX? XXXs botXXX XXXato is in his sXXXach while playing the "XXX-XXX" brand XXX-XXXs. That's so XXX.
PIO: XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. 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.
PSO: XXX? XXXX bottom tomato is in his stomach while playing the "XXXXXXX" 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.
WSN: XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so tom.
Pattern: tom
PIN: XXX? XXXs botXXX XXXato is in his sXXXach while playing the "XXX-XXX" brand XXX-XXXs. That's so XXX.
PIO: XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. 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.
PSO: Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. 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.
WSN: Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX.
</pre>
 
=={{header|AppleScript}}==
Line 68 ⟶ 237:
This uses ASObjC to access macOS's Foundation framework's regex and text-replacement methods. The methods support [https://unicode-org.github.io/icu/userguide/strings/regexp.html ICU]-compatible regular expressions.
 
<langsyntaxhighlight lang="applescript">use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
use scripting additions
Line 124 ⟶ 293:
set output to output as text
set AppleScript's text item delimiters to astid
return output</langsyntaxhighlight>
 
{{output}}
<langsyntaxhighlight lang="applescript">"Redact Tom:
[w|s|n]: XXX? Toms bottom tomato is in his stomach while playing the \"Tom-tom\" brand tom-toms. That's so tom.
[w|i|n]: XXX? Toms bottom tomato is in his stomach while playing the \"Tom-tom\" brand tom-toms. That's so XXX.
Line 142 ⟶ 311:
[p|s|o]: Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing the \"XXXXXXX\" brand XXXXXXXX. That's so XXX.
[p|i|o]: XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the \"XXXXXXX\" brand XXXXXXXX. That's so XXX.
"</langsyntaxhighlight>
Or with the grapheme text:
<langsyntaxhighlight lang="applescript">set graphemeText to "🧑 👨 🧔 👨‍👩‍👦"
set output to {}
repeat with redactionTarget in {"👨", "👨‍👩‍👦"}
Line 155 ⟶ 324:
set output to output as text
set AppleScript's text item delimiters to astid
return output</langsyntaxhighlight>
 
{{output}}
<langsyntaxhighlight lang="applescript">"Redact 👨:
[w]: 🧑 X 🧔 👨‍👩‍👦
 
Redact 👨‍👩‍👦:
[w]: 🧑 👨 🧔 X
"</langsyntaxhighlight>
 
===Vanilla (core language only)===
Line 170 ⟶ 339:
Test code and output as above.
 
<langsyntaxhighlight lang="applescript">on redact(theText, redactionTargets, options)
(* Script object containing the basic process. *)
script default
Line 283 ⟶ 452:
return redactor's outputText
end redact</langsyntaxhighlight>
 
=={{header|AutoHotkey}}==
No Complex Unicode!
<syntaxhighlight lang="autohotkey">str = Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so tom.
words := ["Tom", "tom"]
opts := ["wsn", "win", "psn", "pin", "pso", "pio"]
for i, word in words
{
result .= "Redact '" word "'`n"
for j, opt in opts
result .= opt "`t" redact(str, word, opt) "`n"
result .= "`n"
}
MsgBox, 262144, , % result
return
redact(str, word, opt){
if InStr(opt, "w") ; Whole word
a := "(^|[^-])\K\b", z := "\b(?!-)"
if InStr(opt, "o") ; Overkill
a .= "\b[\w\-]*", z := "[\w\-]*\b" z
if InStr(opt, "i") ; Case insensitive
i := "i)"
ndle := i a "\Q" word "\E" z
while pos := RegExMatch(str, ndle, mtch, A_Index=1?1:pos+StrLen(mtch))
{
rplc := ""
loop % StrLen(mtch)
rplc .= "X"
str := RegExReplace(str, ndle, rplc,, 1)
}
return str
}</syntaxhighlight>
{{out}}
<pre>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.</pre>
 
=={{header|C}}==
This is a very basic ASCII-only implementation, no Unicode or regular expressions.
<langsyntaxhighlight lang="c">#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
Line 355 ⟶ 574:
do_basic_tests("tom");
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 378 ⟶ 597:
=={{header|C++}}==
{{trans|D}}
<langsyntaxhighlight lang="cpp">#include <iostream>
 
using namespace std;
Line 451 ⟶ 670:
example(text, "tom");
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>Redact Tom
Line 470 ⟶ 689:
 
=={{header|D}}==
<langsyntaxhighlight lang="d">import std.stdio;
import std.uni;
 
Line 541 ⟶ 760:
example(text, "Tom");
example(text, "tom");
}</langsyntaxhighlight>
{{out}}
<pre>Redact Tom
Line 558 ⟶ 777:
[p|s|o] Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX
[p|i|o] XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX</pre>
 
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
include "NSLog.incl"
 
local fn Redact( string as CFStringRef, target as CFStringRef, whole as BOOL, icase as BOOL, over as BOOL ) as CFStringRef
ErrorRef err = NULL
CFStringRef w = @"p", i = @"s", o = @"n", result = NULL
NSRegularExpressionOptions options = 0
CFStringRef pattern = fn RegularExpressionEscapedPattern( target )
if whole == YES
pattern = fn StringWithFormat( @"%@%@%@", @"(?<![-[^[:punct:]\\s]])", pattern, @"(?![-[^[:punct:]\\s]])" )
w = @"w"
end if
if over == YES
pattern = fn StringWithFormat( @"%@%@%@", @"[-[^[:punct:]\\s]]*", pattern, @"[-[^[:punct:]\\s]]*+" )
o = @"o"
end if
if icase == YES Then options = NSRegularExpressionCaseInsensitive : i = @"i"
RegularExpressionRef regex = fn RegularExpressionWithPattern( pattern, options, @err )
if err then NSLog( @"%@", fn ErrorLocalizedDescription( err ) )
CFMutableStringRef mutStr = fn MutableStringWithString( string )
CFArrayRef matches = fn RegularExpressionMatches( regex, mutStr, 0, fn CFRangeMake( 0, len( mutStr ) ) )
long x, count = len(matches)
for x = 0 to count - 1
CFRange matchRange = fn ValueRange( fn ObjectValueForKey( matches[x], @"range" ) )
MutableStringReplaceOccurrencesOfString( mutStr, @".(?:\\u200d.)*+", @"X", NSRegularExpressionSearch, matchRange )
next
result = fn StringWithFormat( @"[%@|%@|%@] %@", w, i, o, mutStr )
end fn = result
 
CFStringRef tomTest
tomTest = @"Tom? Toms bottom tomato is in his stomach while playing the \"Tom-tom\" brand tom-toms. That's so tom."
NSLog( @"Test string:\n%@\n\nRedact 'Tom':", tomTest )
NSLog( @"%@", fn Redact( tomTest, @"Tom", YES, NO, NO ) )
NSLog( @"%@", fn Redact( tomTest, @"Tom", YES, YES, NO ) )
NSLog( @"%@", fn Redact( tomTest, @"Tom", NO, NO, NO ) )
NSLog( @"%@", fn Redact( tomTest, @"Tom", NO, YES, NO ) )
NSLog( @"%@", fn Redact( tomTest, @"Tom", NO, NO, YES ) )
NSLog( @"%@", fn Redact( tomTest, @"Tom", NO, YES, YES ) )
NSLog( @"\nRedact 'tom':" )
NSLog( @"%@", fn Redact( tomTest, @"tom", YES, NO, NO ) )
NSLog( @"%@", fn Redact( tomTest, @"tom", YES, YES, NO ) )
NSLog( @"%@", fn Redact( tomTest, @"tom", NO, NO, NO ) )
NSLog( @"%@", fn Redact( tomTest, @"tom", NO, YES, NO ) )
NSLog( @"%@", fn Redact( tomTest, @"tom", NO, NO, YES ) )
NSLog( @"%@", fn Redact( tomTest, @"tom", NO, YES, YES ) )
 
NSLogSetFont( fn FontWithName( @"Menlo", 18.0 ) )
NSLog( @"\n 🧑 👨 🧔 👨‍👩‍👦" )
NSLog( @"Redact '👨': %@", fn Redact( @"🧑 👨 🧔 👨‍👩‍👦", @"👨", YES, YES, YES ) )
NSLog( @"Redact '👨‍👩‍👦': %@", fn Redact( @"🧑 👨 🧔 👨‍👩‍👦", @"👨‍👩‍👦", YES, YES, YES ) )
 
HandleEvents
</syntaxhighlight>
{{output}}
<pre>
Test string:
Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so tom.
 
Redact 'Tom':
[w|s|n] XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so tom.
[w|i|n] XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX.
[p|s|n] XXX? XXXs bottom tomato is in his stomach while playing the "XXX-tom" brand tom-toms. That's so tom.
[p|i|n] XXX? XXXs botXXX XXXato is in his sXXXach while playing the "XXX-XXX" brand XXX-XXXs. That's so XXX.
[p|s|o] XXX? XXXX bottom tomato is in his stomach while playing the "XXXXXXX" brand tom-toms. That's so tom.
[p|i|o] XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX.
 
Redact 'tom':
[w|s|n] Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX.
[w|i|n] XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX.
[p|s|n] Tom? Toms botXXX XXXato is in his sXXXach while playing the "Tom-XXX" brand XXX-XXXs. That's so XXX.
[p|i|n] XXX? XXXs botXXX XXXato is in his sXXXach while playing the "XXX-XXX" brand XXX-XXXs. That's so XXX.
[p|s|o] Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX.
[p|i|o] XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX.
 
🧑 👨 🧔 👨‍👩‍👦
Redact '👨': [w|i|o] 🧑 X 🧔 👨‍👩‍👦
Redact '👨‍👩‍👦': [w|i|o] 🧑 👨 🧔 X
 
</pre>
 
 
=={{header|Go}}==
Line 566 ⟶ 871:
 
To get the number of 'X's right where a ZWJ emoji or other character combination is being replaced, a third party library function is used which counts the number of graphemes in a string, as required by the task.
<langsyntaxhighlight lang="go">package main
 
import (
Line 655 ⟶ 960:
allOpts = []string{"[p]", "[p|o]"}
printResults(text, allOpts, allWords)
}</langsyntaxhighlight>
 
{{out}}
Line 745 ⟶ 1,050:
The solution must kludge a check with the variable "multichar" to properly substitute "X" instead of "XXXX" with the last example.
Otherwise Julia (v 1.4) interprets one 184-bit Unicode extended emoji character as four Unicode characters.
<langsyntaxhighlight lang="julia">function doif_equals(word, pattern, insens=false)
regex = insens ? Regex("^$pattern\$", "i") : Regex("^$pattern\$")
return replace(word, regex => pattern in multichars ? "X" : "X"^length(pattern))
Line 800 ⟶ 1,105:
println()
end
</langsyntaxhighlight>{{out}}
<pre>
 
Line 829 ⟶ 1,134:
=={{header|Lua}}==
Note: The syntax-highlighter used here for Lua appears to be confused by the nested quote styles, but the syntax is valid as written.
<langsyntaxhighlight lang="lua">function redact(text, targ, opts)
local part, case, ovrk = opts:find("p")~=nil, opts:find("s")~=nil, opts:find("o")~=nil
local oknp = ovrk or not part
Line 846 ⟶ 1,151:
print(opts .. " " .. redact(text, targ, opts))
end
end</langsyntaxhighlight>
{{out}}
<pre>Redact 'Tom':
Line 865 ⟶ 1,170:
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
 
Line 907 ⟶ 1,212:
printf "%s %s\n", $option, redact($test, $redact, %$opts)
}
}</langsyntaxhighlight>
{{out}}
<pre style="height:40ex;overflow:scroll;">Redact 'Tom':
Line 969 ⟶ 1,274:
 
=={{header|Phix}}==
{{libheader|Phix/online}}
You can run this online [http://phix.x10.mx/p2js/redact.htm here]. Note the windows console makes a complete mockery of those unicode characters.<br>
Written on the assumption that overkill implies partial (see talk page).<br>
utf32_length() fashioned after [[Reverse_a_string#Phix]] with added ZWJ - I do not expect it to be entirely complete.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>enum WHOLE,PARTIAL,OVERKILL,INSENSITIVE
<span style="color: #008080;">enum</span> <span style="color: #000000;">WHOLE</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PARTIAL</span><span style="color: #0000FF;">,</span><span style="color: #000000;">OVERKILL</span><span style="color: #0000FF;">,</span><span style="color: #000000;">INSENSITIVE</span>
constant spunc = " \r\n\t.?\"" -- spaces and punctuation
<span style="color: #008080;">constant</span> <span style="color: #000000;">spunc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">" \r\n.?\""</span> <span style="color: #000080;font-style:italic;">-- spaces and punctuation</span>
 
function utf32_length(sequence utf32)
<span style="color: #008080;">function</span> <span style="color: #000000;">utf32_length</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">utf32</span><span style="color: #0000FF;">)</span>
integer l = length(utf32)
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">utf32</span><span style="color: #0000FF;">)</span>
for i=1 to l do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
integer ch = utf32[i]
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">utf32</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
if (ch>=0x300 and ch<=0x36f)
<span style="color: #008080;">if</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0x300</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0x36f</span><span style="color: #0000FF;">)</span>
or (ch>=0x1dc0 and ch<=0x1dff)
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0x1dc0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0x1dff</span><span style="color: #0000FF;">)</span>
or (ch>=0x20d0 and ch<=0x20ff)
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0x20d0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0x20ff</span><span style="color: #0000FF;">)</span>
or (ch>=0xfe20 and ch<=0xfe2f) then
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0xfe20</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0xfe2f</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
l -= 1
<span style="color: #000000;">l</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
elsif ch=0x200D then -- ZERO WIDTH JOINER
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0x200D</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- ZERO WIDTH JOINER</span>
l -= 2
<span style="color: #000000;">l</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">2</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return l
<span style="color: #008080;">return</span> <span style="color: #000000;">l</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
 
function redact(string text, word, integer options)
<span style="color: #008080;">function</span> <span style="color: #000000;">redact</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">options</span><span style="color: #0000FF;">)</span>
sequence t_utf32 = utf8_to_utf32(text),
<span style="color: #004080;">sequence</span> <span style="color: #000000;">t_utf32</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">utf8_to_utf32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">),</span>
l_utf32 = t_utf32,
<span style="color: #000000;">l_utf32</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t_utf32</span><span style="color: #0000FF;">,</span>
w_utf32 = utf8_to_utf32(word)
<span style="color: #000000;">w_utf32</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">utf8_to_utf32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
string opt = "[?|s]"
<span style="color: #004080;">string</span> <span style="color: #000000;">opt</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"[?|s]"</span>
if options>INSENSITIVE then
<span style="color: #008080;">if</span> <span style="color: #000000;">options</span><span style="color: #0000FF;">></span><span style="color: #000000;">INSENSITIVE</span> <span style="color: #008080;">then</span>
options -= INSENSITIVE
<span style="color: #000000;">options</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">INSENSITIVE</span>
opt[4] = 'i'
<span style="color: #000000;">opt</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'i'</span>
l_utf32 = lower(t_utf32)
<span style="color: #000000;">l_utf32</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t_utf32</span><span style="color: #0000FF;">)</span>
w_utf32 = lower(w_utf32)
<span style="color: #000000;">w_utf32</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w_utf32</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
opt[2] = "wpo"[options]
<span style="color: #000000;">opt</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"wpo"</span><span style="color: #0000FF;">[</span><span style="color: #000000;">options</span><span style="color: #0000FF;">]</span>
integer idx = 1
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
while true do
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
idx = match(w_utf32,l_utf32,idx)
<span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w_utf32</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l_utf32</span><span style="color: #0000FF;">,</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">)</span>
if idx=0 then exit end if
<span style="color: #008080;">if</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer edx = idx+length(w_utf32)-1
<span style="color: #004080;">integer</span> <span style="color: #000000;">edx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">+</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w_utf32</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span>
if options=WHOLE then
<span style="color: #008080;">if</span> <span style="color: #000000;">options</span><span style="color: #0000FF;">=</span><span style="color: #000000;">WHOLE</span> <span style="color: #008080;">then</span>
if (idx=1 or find(l_utf32[idx-1],spunc))
<span style="color: #008080;">if</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l_utf32</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">spunc</span><span style="color: #0000FF;">))</span>
and (edx=length(l_utf32) or find(l_utf32[edx+1],spunc)) then
<span style="color: #008080;">and</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l_utf32</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l_utf32</span><span style="color: #0000FF;">[</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">spunc</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">then</span>
t_utf32[idx..edx] = repeat('X',utf32_length(t_utf32[idx..edx]))
<span style="color: #000000;">t_utf32</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">..</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'X'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">utf32_length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t_utf32</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">..</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">]))</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
elsif options=PARTIAL
<span style="color: #008080;">elsif</span> <span style="color: #000000;">options</span><span style="color: #0000FF;">=</span><span style="color: #000000;">PARTIAL</span>
or options=OVERKILL then
<span style="color: #008080;">or</span> <span style="color: #000000;">options</span><span style="color: #0000FF;">=</span><span style="color: #000000;">OVERKILL</span> <span style="color: #008080;">then</span>
if options=OVERKILL then
<span style="color: #008080;">if</span> <span style="color: #000000;">options</span><span style="color: #0000FF;">=</span><span style="color: #000000;">OVERKILL</span> <span style="color: #008080;">then</span>
while idx>1 and not find(l_utf32[idx-1],spunc) do idx -= 1 end while
<span style="color: #008080;">while</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l_utf32</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">spunc</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000000;">idx</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
while edx<length(l_utf32) and not find(l_utf32[edx+1],spunc) do edx += 1 end while
<span style="color: #008080;">while</span> <span style="color: #000000;">edx</span><span style="color: #0000FF;"><</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l_utf32</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l_utf32</span><span style="color: #0000FF;">[</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">spunc</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000000;">edx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
t_utf32[idx..edx] = repeat('X',utf32_length(t_utf32[idx..edx]))
<span style="color: #000000;">t_utf32</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">..</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'X'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">utf32_length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t_utf32</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">..</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">]))</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
idx = edx+1
<span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">edx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
text = utf32_to_utf8(t_utf32)
<span style="color: #000000;">text</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">utf32_to_utf8</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t_utf32</span><span style="color: #0000FF;">)</span>
return {opt,text}
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">opt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">text</span><span style="color: #0000FF;">}</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
 
constant test = `
<span style="color: #008080;">constant</span> <span style="color: #000000;">test</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">`
Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so tom.`,
Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so tom.`</span><span style="color: #0000FF;">,</span>
tests = {"Tom","tom","t"}
<span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"Tom"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tom"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"t"</span><span style="color: #0000FF;">}</span>
for t=1 to length(tests) do
<span style="color: #008080;">for</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
printf(1,"Redact %s:\n",{tests[t]})
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Redact %s:\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t</span><span style="color: #0000FF;">]})</span>
for o=WHOLE to OVERKILL do
<span style="color: #008080;">for</span> <span style="color: #000000;">o</span><span style="color: #0000FF;">=</span><span style="color: #000000;">WHOLE</span> <span style="color: #008080;">to</span> <span style="color: #000000;">OVERKILL</span> <span style="color: #008080;">do</span>
printf(1,"%s:%s\n",redact(test,tests[t],o))
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s:%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">redact</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t</span><span style="color: #0000FF;">],</span><span style="color: #000000;">o</span><span style="color: #0000FF;">))</span>
printf(1,"%s:%s\n",redact(test,tests[t],o+INSENSITIVE))
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s:%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">redact</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t</span><span style="color: #0000FF;">],</span><span style="color: #000000;">o</span><span style="color: #0000FF;">+</span><span style="color: #000000;">INSENSITIVE</span><span style="color: #0000FF;">))</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
constant ut = "🧑 👨 🧔 👨‍👩‍👦",
<span style="color: #008080;">constant</span> <span style="color: #000000;">ut</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"🧑 👨 🧔 👨‍👩‍👦"</span><span style="color: #0000FF;">,</span>
fmt = """
<span style="color: #000000;">fmt</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
 
%s
%s
Redact 👨 %s %s
Redact 👨‍👩‍👦👨 %s %s
Redact 👨‍👩‍👦 %s %s
"""
"""</span>
printf(1,fmt,{ut}&redact(ut,"👨",WHOLE)&redact(ut,"👨‍👩‍👦",WHOLE))</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ut</span><span style="color: #0000FF;">}&</span><span style="color: #000000;">redact</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ut</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"👨"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">WHOLE</span><span style="color: #0000FF;">)&</span><span style="color: #000000;">redact</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ut</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"👨‍👩‍👦"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">WHOLE</span><span style="color: #0000FF;">))</span>
<!--</syntaxhighlight>-->
{{out}}
w/p/o means whole/partial/overkill word, s/i means case sensitive/insensitive.
The windows console makes a complete mockery of those unicode characters, though it should look better on linux...
<pre>
Redact Tom:
Line 1,068 ⟶ 1,377:
[o|s]:Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing XXX "XXXXXXX" brand XXXXXXXX. XXXXXX so XXX.
[o|i]:XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing XXX "XXXXXXX" brand XXXXXXXX. XXXXXX so XXX.
 
               🧑 👨 🧔 👨‍👩‍👦
­ƒºæ ­ƒæ¿ ­ƒºö ­ƒæ¿ÔÇì­ƒæ®ÔÇì­ƒæª
Redact 👨 [w|s] 🧑 XX 🧔 👨‍👩‍👦
Redact ­ƒæ¿ [w|s] ­ƒºæ X ­ƒºö ­ƒæ¿ÔÇì­ƒæ®ÔÇì­ƒæª
Redact 👨‍👩‍👦 [w|s] 🧑 👨 🧔 XXXX
Redact ­ƒæ¿ÔÇì­ƒæ®ÔÇì­ƒæª [w|s] ­ƒºæ ­ƒæ¿ ­ƒºö X
</pre>
 
Line 1,078 ⟶ 1,387:
{{works with|Rakudo|2020.02}}
 
<syntaxhighlight lang="raku" perl6line>sub redact ( Str $str, Str $redact, :i(:$insensitive) = False, :p(:$partial) = False, :o(:$overkill) = False ) {
my $rx =
$insensitive ??
Line 1,140 ⟶ 1,449:
printf "%20s %s\n", "Redact '👨' [p|o]", $emoji.&redact('👨', :p, :o);
printf "%20s %s\n", "Redact '👨‍👩‍👦' [p|o]", $emoji.&redact('👨‍👩‍👦', :p, :o);
}</langsyntaxhighlight>
{{out}}
<pre style="height:40ex;overflow:scroll;">Redact 'Tom':
Line 1,214 ⟶ 1,523:
=={{header|REXX}}==
REXX doesn't have &nbsp; ''regular expressions'', &nbsp; so I had to roll-my-own parsing.
<langsyntaxhighlight REXXlang="rexx">/*REXX program redacts a string (using Xs) from a text, depending upon specified options*/
zDefault= 'Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom"' ,
"brand tom-toms. That's so tom."
Line 1,261 ⟶ 1,570:
nz= nz !.head.r || na || !.tail.r
end /*r*/
return strip( translate(nz, 'X', ?) )</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 1,289 ⟶ 1,598:
[p│s│o] Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing XXX "XXXXXXX" brand XXXXXXXX. XXXXXX so XXX.
[p│i│o] XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing XXX "XXXXXXX" brand XXXXXXXX. XXXXXX so XXX.
</pre>
 
=={{header|RPL}}==
≪ DUP2 SWAP 1 DUP SUB POS SIGN DEPTH
→ text seps wip stack <span style="color:grey">@ wip is a flag for a word in progress</span>
≪ wip NOT 1 +
1 text SIZE '''FOR''' j
text j DUP SUB
'''IF''' seps OVER POS wip XOR '''THEN''' + '''ELSE''' 1 wip - 'wip' STO '''END'''
'''NEXT'''
DEPTH stack - 3 + →LIST
≫ ≫ '<span style="color:blue">→TKN</span>' STO <span style="color:grey">@ ( "string" → { wordpos "word" "sep" "word" .. } )</span>
≪ ""
1 3 PICK SIZE '''FOR''' c
OVER c DUP SUB NUM
R→B #20h OR B→R CHR +
'''NEXT''' SWAP DROP
≫ '<span style="color:blue">LOWER</span>' STO
≪ → text pos rep
≪ pos 1 > text 1 pos 1 - SUB "" IFTE
rep +
text pos rep SIZE + OVER SIZE SUB +
≫ ≫ '<span style="color:blue">REPL</span>' STO <span style="color:grey">@ mimics HP-48+ instruction only for strings</span>
≪ DUP2 <span style="color:blue">LOWER</span> SWAP <span style="color:blue">LOWER</span> "" → token word lord loken xxx
≪ xxx 1 7 FS? 9 FS? OR token word IFTE SIZE '''START''' "X" + '''NEXT'''
'''IF''' 7 FC? 9 FC? AND '''THEN'''
'xxx' STO 1 SF loken token
'''DO'''
8 FC? OVER word POS 4 PICK lord POS IFTE
'''IF''' DUP NOT '''THEN''' DROP 1 CF '''ELSE'''
'''IF''' 8 FS? '''THEN''' ROT OVER xxx <span style="color:blue">REPL</span> SWAP '''END'''
xxx <span style="color:blue">REPL</span>
'''END'''
'''UNTIL''' 1 FC? '''END'''
SWAP DROP
'''END'''
≫ ≫ '<span style="color:blue">XREPL</span>' STO <span style="color:grey">@ ( "word" "rd" → "woXX" | "XXXX" ) </span>
≪ DUP 1 GET OVER SIZE '''FOR''' t
DUP t GET <span style="color:blue">LOWER</span>
t SWAP PUT
2 '''STEP'''
≫ '<span style="color:blue">LOTKN</span>' STO <span style="color:grey">@ ( { "TOKENS" } → { "tokens" } ) </span>
≪ 7 9 '''FOR''' f f CF '''NEXT'''
'''IF''' DUP 1 DUP SUB "W" == '''THEN''' 7 SF '''END'''
'''IF''' DUP 2 DUP SUB "I" == '''THEN''' 8 SF '''END'''
'''IF''' 3 DUP SUB "O" == '''THEN''' 9 SF '''END'''
'''IF''' 8 FS? '''THEN''' <span style="color:blue">LOWER</span> '''END'''
SWAP " ,.?'≪≫" <span style="color:blue">→TKN</span> DUP <span style="color:blue">LOTKN</span>
→ word tokens lokens
≪ "" tokens 1 GET
DUP 2 MOD ROT ROT
tokens SIZE '''FOR''' w
8 FS? 'lokens' 'tokens' IFTE w GET
'''IF''' 3 PICK w 2 MOD == '''THEN'''
tokens w GET SWAP
'''IF''' word 7 FS? ≪ == ≫ ≪ POS ≫ IFTE '''THEN''' word <span style="color:blue">XREPL</span> '''END'''
'''END'''
+
'''NEXT'''
≫ ≫ '<span style="color:blue">RDACT</span>' STO <span style="color:grey">@ ( "text" "word" "PAR" → "text" ) </span>
≪ "Tom? Toms bottom tomato is in his stomach while playing the ≪Tom-tom≫ brand tom-toms. That's so tom."
{ "WSN" "WIN" "PSN" "PIN" "PSO" "PIO" } → sentence cases
≪ { }
1 6 '''FOR''' k
sentence "Tom" cases k GET <span style="color:blue">RDACT</span> + '''NEXT'''
1 6 '''FOR''' k
sentence "tom" cases k GET <span style="color:blue">RDACT</span> + '''NEXT'''
≫ ≫ '<span style="color:blue">TASK</span>' STO
{{out}}
<pre>
1: { "XXX? Toms bottom tomato is in his stomach while playing the ≪Tom-tom≫ brand tom-toms. That's so tom."
"XXX? Toms bottom tomato is in his stomach while playing the ≪Tom-tom≫ brand tom-toms. That's so XXX."
"XXX? XXXs bottom tomato is in his stomach while playing the ≪XXX-tom≫ brand tom-toms. That's so tom."
"XXX? XXXs botXXX XXXato is in his sXXXach while playing the ≪XXX-XXX≫ brand XXX-XXXs. That's so XXX."
"XXX? XXXX bottom tomato is in his stomach while playing the ≪XXXXXXX≫ brand tom-toms. That's so tom."
"XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the ≪XXXXXXX≫ brand XXXXXXXX. That's so XXX."
 
"Tom? Toms bottom tomato is in his stomach while playing the ≪Tom-tom≫ brand tom-toms. That's so XXX."
"XXX? Toms bottom tomato is in his stomach while playing the ≪Tom-tom≫ brand tom-toms. That's so XXX."
"Tom? Toms botXXX XXXato is in his sXXXach while playing the ≪Tom-XXX≫ brand XXX-XXXs. That's so XXX."
"XXX? XXXs botXXX XXXato is in his sXXXach while playing the ≪XXX-XXX≫ brand XXX-XXXs. That's so XXX."
"Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing the ≪XXXXXXX≫ brand XXXXXXXX. That's so XXX."
"XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the ≪XXXXXXX≫ brand XXXXXXXX. That's so XXX." }
</pre>
 
=={{header|Swift}}==
{{trans|AppleScript}}
<langsyntaxhighlight lang="swift">import Foundation
 
struct RedactionOptions: OptionSet {
Line 1,378 ⟶ 1,776:
doExtraTest(target: "👨")
print()
doExtraTest(target: "👨‍👩‍👦")</langsyntaxhighlight>
 
{{out}}
Line 1,407 ⟶ 1,805:
=={{header|Tailspin}}==
This is using the normal definition of words, i.e. emoji do not form words or word boundaries, so the stretch assignment must be matched as a partial match. This solution parses the flags inline and takes the secret to be redacted as a parameter to illustrate both options, although in a production solution I would imagine one might pass both the same way.
<langsyntaxhighlight lang="tailspin">
composer redact&{secret:}
@: { fill: '', leftBound: '\b{g}', rightBound: '\b{g}', case: '' };
Line 1,444 ⟶ 1,842:
$;
' -> !OUT::write
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,473 ⟶ 1,871:
{{libheader|Wren-str}}
{{libheader|Wren-upc}}
<langsyntaxhighlight ecmascriptlang="wren">import "./pattern" for Pattern
import "./str" for Str
import "./upc" for Graphemes
 
var join = Fn.new { |words, seps|
Line 1,543 ⟶ 1,941:
text = "Argentina🧑🇦🇹 France👨🇫🇷 Germany🧔🇩🇪 Netherlands👨‍👩‍👦🇳🇱"
allOpts = ["[p]", "[p|o]"]
printResults.call(text, allOpts, allWords)</langsyntaxhighlight>
 
{{out}}
9,482

edits