Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Friday Fun – A PowerShell Nonsense Challenge

Posted on August 7, 2020September 30, 2020

Today I thought I'd share my PowerShell solution to a recent Iron Scripter challenge. The challenge was to create PowerShell code that would create nonsense documents, with a goal of creating 10 sample files filled with gibberish. Yes, other than maybe wanting some test files to work with, on its face the challenge appears pointless.  However, as with all of these challenges, or even the ones in The PowerShell Practice Primer, the journey is the reward. The true value is learning how to use PowerShell, and maybe discovering a new technique or command. The hope is that during the course of working on the challenge, you'll improve your PowerShell scripting skills. And who knows, maybe even have a little fun along the way.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

Nonsense Documents

I've put everything in a module on Github called PSNonsense.

I approached this in a building block approach. I begin with a function to create a nonsense word. This is simple enough. All I need to do is select a number of random characters from a pool and join them together.

$letters = [Char[]]'abcdefghijklmnopqrstuvwxyz'
  #add some diacritical characters
  $letters += [Char]0x00EB,[Char]0x00E4,[Char]0x00E9

  -join ( $letters | Get-Random -count $Length)

The function, as do all of the functions, includes parameters to define the length or count, using a random default. I also use a ValidateSet attribute to verify the parameter value a user might enter.

Param(
    [Parameter(Position = 0, HelpMessage = "Indicate the word length between 1 and 10.")]
    [ValidateRange(1, 10)]
    [int]$Length = (Get-Random -Minimum 1 -Maximum 10)
  )

Creating a nonsense word is this easy.

PS C:\> New-NonsenseWord -Length 7
ëfswäna

A nonsense sentence is just a collection of nonsense words. But there was an additional challenge to insert punctuation and to make sure sentences ended in a period. I added code to randomly end some sentences in a question mark or exclamation point.

$punct = ", ", "; ", " - ", ": "
  #define a flag to indicate if random punctuation has been inserted.
  $NoPunct = $true

  1..($WordCount - 1) | ForEach-Object -Begin {
    #make sure we start the sentence with a word
    [string]$sentence = New-NonsenseWord
  } -process {
    #insert random punctuation into the sentence, but only once
    if (($WordCount -ge 10) -AND (Test) -AND $NoPunct) {
      $sentence += $punct | Get-Random -Count 1
      $NoPunct = $False
    }
    $sentence += "{0} " -f (New-NonsenseWord)
  }

  #capitalize the first word of the sentence.
  #does the sentence end in a period, exclamation or question mark.
  #The period should be the default most of the time
  $rn = Get-Random -Maximum 100 -Minimum 1
  Switch ($rn) {
    {$_ -ge 90} {$end = "?" ; break}
    {$_ -ge 82} { $end = "!"}
    Default { $end = "."}
  }

  $out = "{0}{1}{2}" -f ([string]$sentence[0]).ToUpper(), $sentence.substring(1).TrimEnd(),$end

The function includes a private function called Test which randomly determines if I should do something, like insert punctuation.

PS C:\> New-NonsenseSentence -WordCount 11
Urip; élthe qkvipwen kym h fäuq cwuoéhjnä ikafysqol eom ikäb yke.

Creating a paragraph means joining a specified number of sentences together.

$raw = 1..$SentenceCount | Foreach-object {New-NonsenseSentence}
  ($raw -join " ").trimend()

Since samples are getting a bit longer, here's a screen shot.

nnp

Notice the puncutation.

Creating a document is nothing more than a collection of paragraphs.

#insert a return after each paragraph
  1..$ParagraphCount | ForEach-Object {New-NonsenseParagraph;"`r"}

With this function, New-NonsenseDocument, I can use code like this to create 10 documents.

1..10 | ForEach-Object {
    $filename = [System.IO.Path]::GetRandomFileName()
    #replace the extension
    $filename = $filename -replace "\.\w+", ".txt"
    #build the path
    $path = Join-Path -path $env:TEMP -ChildPath $filename
    #create the document
    #encode as UTF8 to save the diacritical characters
    New-NonsenseDocument -ParagraphCount (Get-Random -Minimum 3 -Maximum 10) | 
    Out-File -FilePath $path -Encoding utf8
    #view the result
    Get-Item $path
}

I'm useing the .NET Framework to generate a randome file name and then using a regex pattern to replace the extension with .txt extension. The final file path is built using Join-Path which is recommended instead of trying to concatenate strings together. You can view the files in the Samples folder in the PSNonsense repository.

Markdown Nonsense

The challenge had an extra-credit requirement to create a nonsense markdown document. A markdown document has specific requirements for headings. Ultimately, I built the file by using a here-string, and inserting randomly generated markdown elements.

To simplify things (honestly), I wrapped the PSNonsense commands into a few helper, or cheater, functions.

function New-Heading {
    (New-NonsenseSentence -WordCount (Get-Random -Minimum 1 -Maximum 5)) -replace "[.!?]", ""
}

function New-CodeFence {
    $cmd = "$((New-NonsenseSentence -WordCount (Get-Random -Minimum 2 -Maximum 6)) -replace "[.!?]",'')"

    #the backtick needs to be escaped so that end result is a proper markdown code fence.
    #there should be 6 backticks.
    $cf = @"
$('`'*6)powershell
PS C:\> $cmd
$('`'*6)
"@
    $cf
}

function New-SubHead {
    Param(
        [int]$Level = 2
    )

    $h = "#"*$level
    $head = "{0} {1}" -f $h, (New-Heading)
    #write-host $head -ForegroundColor red
    $out = @"
$head


"@

    1..(Get-Random -Maximum 4) | ForEach-Object {

        $p = (New-NonsenseParagraph -SentenceCount (Get-Random -Minimum 4 -Maximum 10) -outvariable pv)

        if ((Get-Random)%3) {
            #randomly format a string
            $wds = ($p.split()).where( {$_ -match "\w+"})
            $hl = $wds | Select-Object -skip (Get-Random -Minimum 7 -Maximum ($wds.count - 20)) -First (Get-Random -Minimum 1 -Maximum 7)

            #randomly decide how to format
            Switch ((Get-Random)) {
                {$_%3} {$f = "*$($hl -join " ")*" }
                {$_%5} {$f = "__$($hl -join " ")__"}
                {$_%7} {$f = "__*$($hl -join " ")*__" }
                {$_%4} {$f = "``$($hl -join " ")``" }
                {$_%2} {$f = "[$($hl -join " ")](https://www.$(New-NonsenseWord).com)"}
            }
            #left justify to send to the here string to avoid extra spaces
            $out += ($p -replace ($hl -join " "), $f)
        } #if %3
        else {
            $out += $p
        }

        $out += "`n`n"

        <#
        the out variable is itself an array. I want to get the first item in that array,
        which will be a string and then the first character in that string.
        #>
        if ($pv[0][0] -match "[aeifuylm]") {
            #$out+="`n"
            #increment if the next level is 4 or less
            if ($level + 1 -le 4) {
                $out += New-SubHead -level ($level + 1)
            }
            else {
                #repeat the level
                $out += New-SubHead -level $level
            }
        }
        elseif ($pv[0][0] -match "[pjqrst]" ) {

            $out += New-CodeFence
            $out += "`n`n"
            #add a bit more verbiage
            $out += New-NonsenseParagraph -SentenceCount (Get-Random -Minimum 1 -Maximum 4)
        }
    } #foreach object

    $out

} #New-SubHead

I gave myself even more of a challenge by randomly inserting code fence sections, and formatting random phrases. I think the comments in the functions explain my thought process. With these functions, and my PSNonsense module, I can run code like this to create a nonsense markdown document.

$md = @"
# $(New-Heading)

$((New-SubHead).trimend())

__My additional New-Headings follow.__


"@

1..(Get-Random -maximum 5) | ForEach-Object {
    $md += New-SubHead
}

$md += "Updated *$(Get-Date)*."

$md
#encode as UTF8 to save the diacritical characters
$md | Out-File -FilePath c:\work\nonsense.md -Encoding utf8

The here-strings include the necessary blank lines to create a proper markdown document. Note the message about file encoding. If you use special characters and don't specify UTF8, the file might have '?' characters in place. One thing I noticed in VS Code is that in editor mode the markdown document is fine. But when I use the preview mode, it doesn't detect the special characters. I don't iknow if it is a bug or a setting I haven't found yet. Regardless, you can find my nonsense markdown and a PDF version in the Samples folder on Github.

I hope you'll take some time to look at code in the module's repository. Ideally, you'll try it out yourself to see how it works and why. If you learn something new, I hope you'll let me know.

In the mean time, keep using PowerShell every day. And if you haven't, checkout the other scripting challenges at https://ironscripter.us and try your hand at solving them. There's no time limit or expiration date and you might be surprised what you learn.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

1 thought on “Friday Fun – A PowerShell Nonsense Challenge”

  1. Pingback: Creating Nonsense Documents with Powershell – Curated SQL

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d