XXXX redacted: Difference between revisions

Add ed example
m (syntax highlighting fixup automation)
(Add ed example)
 
(6 intermediate revisions by 5 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 608 ⟶ 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|ed}}==
 
Uses non-portable [[GNU Ed]] extension for case-insensitive matching. The number of replacement lines has to be copy-pasted as many times as necessary for full replacement. Because, unlike [[sed]], ed has no loops. Also note that the replacement is always three X-es, because ed has no way to customize the replacement length.
 
<syntaxhighlight lang="sed">
H
2,j
1s/.*/&|/
,j
t
t0
t0
t0
t0
t0
# Repeat as many times as possible. Because ed has no loops
1s/^(.*)\|(.*)\b\1\b/\1|\2XXX/g
1s/^(.*)\|(.*)\b\1\b/\1|\2XXX/g
1s/^(.*)\|(.*)\b\1\b/\1|\2XXX/g
1s/^(.*)\|(.*)\b\1\b/\1|\2XXX/g
1s/^(.*)\|(.*)\b\1\b/\1|\2XXX/g
1s/^(.*)\|(.*)\b\1\b/\1|\2XXX/g
1s/^(.*)\|(.*)\b\1\b/\1|\2XXX/g
1s/^(.*)\|(.*)\b\1\b/\1|\2XXX/g
1s/^(.*)\|(.*)\b\1\b/\1|\2XXX/g
1s/^(.*)\|(.*)\b\1\b/\1|\2XXX/g
1s/^(.*)\|(.*)$/\2/
2s/^(.*)\|(.*)\b\1\b/\1|\2XXX/gi
2s/^(.*)\|(.*)\b\1\b/\1|\2XXX/gi
2s/^(.*)\|(.*)\b\1\b/\1|\2XXX/gi
2s/^(.*)\|(.*)\b\1\b/\1|\2XXX/gi
2s/^(.*)\|(.*)\b\1\b/\1|\2XXX/gi
2s/^(.*)\|(.*)\b\1\b/\1|\2XXX/gi
2s/^(.*)\|(.*)\b\1\b/\1|\2XXX/gi
2s/^(.*)\|(.*)\b\1\b/\1|\2XXX/gi
2s/^(.*)\|(.*)\b\1\b/\1|\2XXX/gi
2s/^(.*)\|(.*)\b\1\b/\1|\2XXX/gi
2s/^(.*)\|(.*)$/\2/
3s/^(.*)\|(.*)\1/\1|\2XXX/g
3s/^(.*)\|(.*)\1/\1|\2XXX/g
3s/^(.*)\|(.*)\1/\1|\2XXX/g
3s/^(.*)\|(.*)\1/\1|\2XXX/g
3s/^(.*)\|(.*)\1/\1|\2XXX/g
3s/^(.*)\|(.*)\1/\1|\2XXX/g
3s/^(.*)\|(.*)\1/\1|\2XXX/g
3s/^(.*)\|(.*)\1/\1|\2XXX/g
3s/^(.*)\|(.*)\1/\1|\2XXX/g
3s/^(.*)\|(.*)\1/\1|\2XXX/g
3s/^(.*)\|(.*)$/\2/
4s/^(.*)\|(.*)\1/\1|\2XXX/gi
4s/^(.*)\|(.*)\1/\1|\2XXX/gi
4s/^(.*)\|(.*)\1/\1|\2XXX/gi
4s/^(.*)\|(.*)\1/\1|\2XXX/gi
4s/^(.*)\|(.*)\1/\1|\2XXX/gi
4s/^(.*)\|(.*)\1/\1|\2XXX/gi
4s/^(.*)\|(.*)\1/\1|\2XXX/gi
4s/^(.*)\|(.*)\1/\1|\2XXX/gi
4s/^(.*)\|(.*)\1/\1|\2XXX/gi
4s/^(.*)\|(.*)\1/\1|\2XXX/gi
4s/^(.*)\|(.*)$/\2/
5s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/g
5s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/g
5s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/g
5s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/g
5s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/g
5s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/g
5s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/g
5s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/g
5s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/g
5s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/g
5s/^(.*)\|(.*)$/\2/
6s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/gi
6s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/gi
6s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/gi
6s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/gi
6s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/gi
6s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/gi
6s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/gi
6s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/gi
6s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/gi
6s/^(.*)\|(.*)\b(\w*)\1(\w*)\b(.*)$/\1|\2XXX\5/gi
6s/^(.*)\|(.*)$/\2/
# Pretty descriptions
1s/.*/Whole word: &/
2s/.*/Whole word, case insensitive: &/
3s/.*/Partial word: &/
4s/.*/Partial word, case insensitive: &/
5s/.*/Partial word, overkill: &/
6s/.*/Partial word, case insensitive, overkill: &/
,p
Q</syntaxhighlight>
 
{{out}}
 
<pre>$ cat xxx-redacted.ed | ed -lEGs xxx-redacted.input
Whole word: XXX? Toms bottom tomato is in his stomach while playing the "XXX-tom" brand tom-toms. That's so tom.
Whole word, case insensitive: XXX? Toms bottom tomato is in his stomach while playing the "XXX-XXX" brand XXX-toms. That's so XXX.
Partial word: XXX? XXXs bottom tomato is in his stomach while playing the "XXX-tom" brand tom-toms. That's so tom.
Partial word, case insensitive: XXX? XXXs botXXX XXXato is in his sXXXach while playing the "XXX-XXX" brand XXX-XXXs. That's so XXX.
Partial word, overkill: XXX? XXX bottom tomato is in his stomach while playing the "XXX-tom" brand tom-toms. That's so tom.
Partial word, case insensitive, overkill: XXX? XXX XXX XXX is in his XXX while playing the "XXX-XXX" brand XXX-XXX. That's so XXX.</pre>
 
=={{header|FreeBASIC}}==
{{trans|D}}
No Complex Unicode!
<syntaxhighlight lang="vbnet">Function isWordChar(c As String) As Integer
Return (c = "-" Or c >= "A" And c <= "Z" Or c >= "a" And c <= "z")
End Function
 
Function Redact(source As String, word As String, partial As Boolean, insensitive As Boolean, overkill As Boolean) As String
Dim As Integer i, j, beg, fin, match
Dim As String temp, s, w
temp = source
i = 1
While i <= Len(temp) - Len(word) + 1
match = 1
j = 1
While j <= Len(word)
s = Mid(temp, i + j - 1, 1)
w = Mid(word, j, 1)
If insensitive Then
If Lcase(s) <> Lcase(w) Then
match = 0
Exit While
End If
Else
If s <> w Then
match = 0
Exit While
End If
End If
j += 1
Wend
If match Then
beg = i
fin = i + Len(word) - 1
If Not partial Then
If beg > 1 And isWordChar(Mid(temp, beg - 1, 1)) Then
i += 1
Continue While
End If
If fin < Len(temp) And isWordChar(Mid(temp, fin + 1, 1)) Then
i += 1
Continue While
End If
End If
If overkill Then
While beg > 1 And isWordChar(Mid(temp, beg - 1, 1))
beg -= 1
Wend
While fin < Len(temp) And isWordChar(Mid(temp, fin + 1, 1))
fin += 1
Wend
End If
Mid(temp, beg, fin - beg + 1) = String(fin - beg + 1, "X")
End If
i += 1
Wend
Return temp
End Function
 
Sub Example(source As String, word As String)
Print "Redact '"; word; "':"
Print "[w|s|n] "; Redact(source, word, False, False, False)
Print "[w|i|n] "; Redact(source, word, False, True, False)
Print "[p|s|n] "; Redact(source, word, True, False, False)
Print "[p|i|n] "; Redact(source, word, True, True, False)
Print "[p|s|o] "; Redact(source, word, True, False, True)
Print "[p|i|o] "; Redact(source, word, True, True, True)
Print
End Sub
 
Dim As String text
text = "Tom? Toms bottom tomato is in his stomach while playing the ""Tom-tom"" brand tom-toms. That's so tom"
Example(text, "Tom")
Example(text, "tom")
 
Sleep</syntaxhighlight>
{{out}}
<pre>Same as D entry.</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 1,128 ⟶ 1,563:
</pre>
 
=={{header|RakuPython}}==
{{works with|Python|3.x}}
{{trans|D}}
<syntaxhighlight lang="python">#!/usr/bin/env python3
 
def redact(source, word, partial=False, insensitive=False, overkill=False):
def different(s, w):
if insensitive:
return s.upper() != w.upper()
else:
return s != w
 
def is_word_char(c):
return c == '-' or c.isalpha()
 
temp = list(source)
i = 0
while i <= len(temp) - len(word):
match = True
j = 0
while j < len(word):
if different(temp[i + j], word[j]):
match = False
break
j += 1
if match:
beg = i
end = i + len(word)
if not partial:
if beg > 0 and is_word_char(temp[beg - 1]):
i += 1
continue
if end < len(temp) and is_word_char(temp[end]):
i += 1
continue
if overkill:
while beg > 0 and is_word_char(temp[beg - 1]):
beg -= 1
while end < len(temp) - 1 and is_word_char(temp[end]):
end += 1
for k in range(beg, end):
temp[k] = 'X'
i += 1
return ''.join(temp)
 
def example(source, word):
print("Redact '", word, "':")
print("[w|s|n]", redact(source, word, False, False, False))
print("[w|i|n]", redact(source, word, False, True, False))
print("[p|s|n]", redact(source, word, True, False, False))
print("[p|i|n]", redact(source, word, True, True, False))
print("[p|s|o]", redact(source, word, True, False, True))
print("[p|i|o]", redact(source, word, True, True, True))
print()
 
if __name__ == "__main__":
text = 'Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That\'s so tom'
example(text, "Tom")
example(text, "tom")
</syntaxhighlight>
 
=={{header|Raku}}==
{{works with|Rakudo|2020.02}}
 
Line 1,343 ⟶ 1,838:
[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>
 
Line 1,527 ⟶ 2,111:
{{libheader|Wren-str}}
{{libheader|Wren-upc}}
<syntaxhighlight lang="ecmascriptwren">import "./pattern" for Pattern
import "./str" for Str
import "./upc" for Graphemes
 
var join = Fn.new { |words, seps|
100

edits