Picking Best Approach: Example Capitalizing Words (Part 2)

by Feb 14, 2023

In PowerShell, there are four separate sources of commands you can pick from when trying to solve a problem. In this mini-series, we look at all of them. The problem to solve is always the same: how to capitalize the first letter in a word. Note that this is an arbitrary problem we just picked as an example. The solution strategies apply to any problem you may want to solve with PowerShell.

The easiest way to solve a problem in PowerShell is to use the appropriate PowerShell cmdlet. In Part 1 we already discovered that there was no specialized PowerShell cmdlet that could do the trick, so you were forced to use low-level methods to solve the task anyway.

Since we now have a solution, let’s just turn the code below into a brand-new PowerShell cmdlet (so we never need to invent this solution again, plus our production code becomes smaller and easier to understand and review):

 $text = "thIS is    A  TEST teXT"
 # split text in words
 $words = $text -split '\s{1,}' |
 # use ForEach-Object to break down the problem to solving ONE instance of your problem
 # regardless of how many words there are, the following script block deals with
 # one word at a time:
 ForEach-Object  {
     $theWord = $_
     # use .NET string methods on the object to solve your issue:
     $theWord.SubString(0,1).toUpper() + $theWord.SubString(1).ToLower()
 }
 
 # the result is a string array. Use the -join operator to turn it into ONE string:
 $result = $words -join ' '
 $result

Turning a piece of code into a reusable cmdlet is always using the same few steps: wrap your code inside a function, and define its inputs (aka parameter) i.e. like this:

function Convert-CapitalizeWord
{
    param
    (
        [Parameter(Mandatory,ValueFromPipeline)]
        $Text
    )
    
    process
    {
        # split text in words
        $words = $Text -split '\s{1,}' |
        # use ForEach-Object to break down the problem to solving ONE instance of your problem
        # regardless of how many words there are, the following script block deals with
        # one word at a time:
        ForEach-Object  {
            $theWord = $_
            # use .NET string methods on the object to solve your issue:
            $theWord.SubString(0,1).toUpper() + $theWord.SubString(1).ToLower()
        }
 
        # the result is a string array. Use the -join operator to turn it into ONE string:
        $result = $words -join ' '
        $result 
    }
}

We have boldened the text that was appended at the beginning and added at the end. The code that does the job (in this case the text conversion) remains unchanged inside the function (which is why we colorized it in black).

When you run the code above, PowerShell sets up your new function. Then, you can use it as often as you want, and since it is pipeline-aware, you can even pipe text from other cmdlets to it. If you wanted, you could now use Get-Content to read an entire text file and let Convert-CapitalizeWord capitalize each word in it – functions are the miracles inside PowerShell that make code reusable and scalable:

 
# you get automatic prompts when you forget to submit mandatory arguments:
PS> Convert-CapitalizeWord
cmdlet Convert-CapitalizeWord at command pipeline position 1
Supply values for the following parameters:
Text: heLLO WOrld
Hello World

# you can submit your text to the -Text parameter:
PS> Convert-CapitalizeWord -Text 'this iS a LONG teXT'
This Is A Long Text

# you can pipe as many texts as you like (scalable) via the pipeline:
PS> 'Hello world!', 'someTHING else' | Convert-CapitalizeWord
Hello World!
Something Else  
 

You can copy/paste your function into scripts where you need it.

In order for functions to be recognized and loaded automatically (like all the other “built-in” PowerShell cmdlets), and serve as a permanent command extension for you shell, you would need to store your function inside a module.

For now, the take-away is: by wrapping code inside functions, you make your code reusable, you automatically add scalability (in our example above we now could convert one or thousands of strings in the same call), and your production script code becomes shorter and can focus on what it really wants to accomplish.


Tweet this Tip! Tweet this Tip!