Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell script indentation for long strings

Tags:

powershell

This problem does not have to be solved this way, but it would save me a lot of precious time if it can be:

I have been logging "line at a time" to a log file. Like this:

$mylogentry = "A string of text containing information"
$mylogentry | out-file -append $log_file_path
$array_of_log_entries += $mylogentry

The reason for the array is that I join them into a Send-Message body.

When I have long quotes however, I like to break them across lines. I can do this using the backtick '`' character. What I have never worked out is how to escape tabs if the quote line is nested under something else. Using backtick before each indentation doesn't remove the tab.

If you look at sites like this: http://technet.microsoft.com/en-us/magazine/hh475841.aspx you'll see that even while he is encouraging indentation, his code is not indented for the parameters. (You can actually tab those in because whitespace is ignored outside of quotes. Maybe he was just making a point)

This is an attempted example at what I mean. (Note Im having trouble replicating the formatting on SE. 4 space indent doesn't seem to create a code block anymore)

if($somecondition){
   $mylogentry = "A string of really long text for non-technical people `
` ` continue to write text here. Additional info (technical): $techvar"

That string would have a big gap between 'people' and 'continue' due to my indenting. I can of course have 'continue' begin at column 0 but then my code looks even more stupid.

like image 549
BSAFH Avatar asked Oct 14 '14 23:10

BSAFH


People also ask

How do I indent a PowerShell script?

Use four spaces per indentation level Usually you will press the [Tab] key to indent, but most editors can be configured to insert spaces instead of actual tab characters. For most programming languages and editors (including PowerShell ISE) the default is four spaces, and that's what we recommend.

What does :: mean in PowerShell?

From the about_Operators help topic: :: Static member operator Calls the static properties operator and methods of a .NET Framework class. To find the static properties and methods of an object, use the Static parameter of the Get-Member cmdlet. [

What does @{} mean in PowerShell?

Hash table literal syntax @{} Similar to the array subexpression, this syntax is used to declare a hash table.

How do you split a string in PowerShell?

Use one of the following patterns to split more than one string: Use the binary split operator (<string[]> -split <delimiter>) Enclose all the strings in parentheses. Store the strings in a variable then submit the variable to the split operator.


2 Answers

I'd like to share some options in addition to other answers.

Joining array of substrings (explicit)

Unary -join operator

$singleLineText = -join @(
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
    "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
    "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
    "commodo consequat."
)

Binary -join operator

$singleLineText = @(
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod"
    "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim"
    "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea"
    "commodo consequat."
) -join ' '

Pros:

  • No plus signs (+) or commas (,) needed.
  • Easy switch to binary -join "`r`n" operator for multiline string.
  • Free to use desired indentations.

Cons:

  • Text manipulations can be tiresome.

Joining array of substrings (implicit) | avoid

Appending to an empty string.

$singleLineText = '' + @(
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod"
    "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,"
    "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo"
    "consequat."
)

Piping to script block and using $input - an automatic variable.

$singleLineText = @(
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod"
    "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,"
    "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo"
    "consequat."
) | & { "$input" }

Whenever an array is coerced into a string, [System.String]::Join(separator, array) method is applied implicitly. Where the separator is " " (space) by default, and can be overwritten by setting $OFS - the Ouptut Field Sperator special variable.

Pros:

  • Suited for joining pipe output.

Cons:

  • Lack of clarity (for several reasons), thus should be avoided whenever possible.

Here-string

$singleLineText = @"
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
"@ -replace "`r" -replace "`n", ' '

Pros:

  • Good for drop-in big sheets of arbitrary preformatted text (like source code).
  • Preserves source indentations.
  • No need to escape quotes.

Cons:

  • Not friendly to script formatting.
  • Can be hard to keep track of trailing white-spaces.

The addition assignment operator (+=)

$s =  "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do ";
$s += "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad ";
$s += "minim veniam, quis nostrud exercitation ullamco laboris nisi ut ";
$s += "aliquip ex ea commodo consequat.";

Pros:

  • Most obvious, universal and well-known syntax (outside of PowerShell).
  • Mostly programming language agnostic *.

* Variable naming conventions may be violated in some programming languages.

Cons:

  • Text manipulations can be tiresome.
like image 60
Dmitriy Work Avatar answered Sep 20 '22 12:09

Dmitriy Work


You can't escape away the tabs or spaces you inserted into the string; they're inside the quotes and part of the string now (and so are the line breaks for that matter).

You have a few options:

  1. Don't break the string at all; let it ride. Obviously not what you want to do, but it works.
  2. Use @Matt's suggestion and concatenate the strings. As long as the quotes begin after the indentation, you'll be fine.
  3. Don't indent the next lines. This assumes you do want the line breaks as part of the string. It can look messy, but it will be a) readable without scrolling and b) functional. It looks something like this:

    if ($fakeCondition) {
        if ($fauxCondition) {
            $longString = "Hello this string is too long 
    to be just one big line so we'll break it up into 
    some smaller lines for the sake of readability."
            # Code that uses the string
            Write-Host $longString
        }
    }
    
  4. Other stuff: use an array with one element for each line and then join it, or use .NET's StringBuilder, but those are overkill to solve what is essentially a formatting annoyance for you.

    Here strings (using @" to begin a string and "@ to end it) will have the same problem as option 3 (the lines cannot be indented or the tabs/spaces will be embedded in the string).

My View

When I run into this issue of long strings polluting the code, I usually start to rethink embedding the strings, or where I'm embedding them.

I might break this functionality into a function, then accept the string as a parameter (pushing the problem off to a different part of the code, but it can be helpful).

Sometimes I'll put it into a here document or long string at the top of the script and then use the variable later on.

Sometimes it means saving these strings in a separate file and reading the contents at run time.

All depends on the situation.

like image 20
briantist Avatar answered Sep 21 '22 12:09

briantist