Partilhar via


Check Spelling Script

After reading Marcel's introductory piece on ScriptBlock, I decided to rewrite an old script of mine that checks the spelling of all text files in a directory. Here is what I came out with.

#region Parse a line to a list of words

$StringFind =
{param ($str, $start, $cond)
if ($start -ge 0 -and $start -lt $str.Length) {
for($i = $start; $i -lt $str.Length; $i++) {
if (& $cond $str[$i]) {
return $i
}
}
}
return $str.Length
}

$IsLetter =
{param ([char]$c) [char]::isletter($c)}

$IsNotLetter =
{param ([char] $c) ! (& $IsLetter $c)}

function ParseFileForWord
{param ([string]$str)
$end = 0
for ($start = & $StringFind $str $end $IsLetter;
$start -lt $str.Length;
$start = & $StringFind $str ($end + 1) $IsLetter) {
$end = & $StringFind $str $start $IsNotLetter
write-object $str.substring($start, ($end - $start))
}
}

#endregion Parse a line to a list of words

$wordApp = New-Object -com Word.Application

get-content (dir *.txt) | foreach {ParseFileForWord $_} | where {!$wordApp.CheckSpelling($_)} | Sort -unique

$wordApp.quit()

A couple of things here. First I used a script block to parameterize StringFind. This saves me from writing similar-looking code for two functions: one to find the next letter in a string and the other to find the next non-letter . To accomplish the former I do $StringFind $str $i $IsLetter while $StringFind $str $i $IsNotLetter does the latter. Also, thanks to New-Object's COMOBJECT parameter, it takes only several lines to carry out the spelling check part.

Comments

  • Anonymous
    December 19, 2005
    Why should one be reliant on MS Office Word to be installed for a spell checker. The operating system should have a universal speller for every supported language. Is it so difficult to implement? Many other applications would benefit. All text boxes should have a speller associated with them.
  • Anonymous
    December 22, 2005
    This is a very good illustration of the power of ScriptBlock. The syntax with '&' is a bit awkward. It would be cool if you can pass a function name in directly. But this is still very cool. Thanks!