Hash tables are indeed preferable for most things. But in this case, if you're wanting to replace the actual word, it requires a loop somewhere in the process.

If you really MUST use a hash table for something like this, you want to keep loops to a minimum. Such as this:

Code:
; Add a bad word, /abword word; (just one word)
alias abword { 
  if ($0 == 1) { hadd -m bword $1 /\b( $+ $1  $+ )\b/gi | vbword | sbword }
  else { echo -agc info *** Error: Invalid parameters. Must be one word only. }
}
; Delete a bad word, /dbword word;
alias dbword {
  if ($0 == 1) { hdel bword $1 | vbword | sbword }
  else { echo -agc info *** Error: Invalid parameters. Must be one word only. }
}
; View bad words, /vbword;
alias vbword { 
  var %i = 1
  while ($hget(bword,%i).item) {
    var %bwords = %bwords $v1
    if ($len(%bwords) > 200) { echo -ag Bwords: %bwords | var %bwords }
    inc %i 
  }
  if (%bwords) { echo -ag Bwords: %bwords }
}
; $curse($1-); Censors text based upon "bword" hash table.
alias cursef {
  var %i = 1 , %text = $1-
  while ($hfind(bword,$1-,%i,R).data) {
    var %text = $regsubex(%text,$hget(bword,$v1),$str(*,$len(\t)))
    inc %i
  }
  return %text
}
; Save the hash table, /sbword
alias sbword { if ($hget(bword)) { hsave -i bword bword.ini bword } }
; Load the hash table, /lbword
alias lbword { 
  if ($hget(bword)) { hfree bword }
  hmake bword 100
  if ($isfile(bword.ini)) { hload -i bword bword.ini bword }
}
on *:start:{ lbword }


The way I made this though, was mainly meant to be quick. So it doesn't support "multi-word swear words." I could change that of course, but then it'd require you to use a -different- way to delete the words (example: you'd probably need a dialog).

The commands would be:

/abword; -- Adds a word.
/dbword; -- Deletes a word.
/vbword; -- Shows badword list.
/sbword; -- Save the badword list. (This is triggered automatically after adding a word or deleting a word with the /abword and /dbword aliases.)
/lbword; -- This loads the badword.ini list into the bword hash table.
$cursef($1-); -- This returns the "censored" text.


I still suggest just using a variable to hold the vars, rather than using a hash table. Much cleaner.