Von Holger Voges auf Samstag, 06. Februar 2016
Kategorie: Tipp

Texte umschliessen und kommaseparierte Listen erstellen in Powershell

Ein häufig auftretendes Problem ist das umschliessen von Texten z.B. mit Anführungszeichen. Für Transact-SQL gibt es dafür sogar eine eigenen Funktion, Quotename, die das übernimmt. In Powershell fehlt diese Funktion zwar, sie lässt sich aber durch den Format-Operator -f sehr einfach nachrüsten. Der Format-Operator kann in einen String beliebige Texte einfügen. Im Text werden dafür Platzhalter definiert. Ein Platzhalter ist ein Zahl, die in geschweifte Klammern eingeschlossen ist, z.B. {0}. Hinter dem Text folgt der Format-Operator -f, wiederum gefolgt von den Werten, die in die Platzhalter eingefügt werden sollen:

'Dies ist ein {0} Text mit {2} Platzhaltern, der als {1} dient' -f "sinnloser","Beispiel","drei"

Das Prinzip ist sehr einfach. Hinter dem -f folgen 3 Strings, die durch Kommas getrennt sind. Die Strings werden von 0 ab durchgezählt und in die entsprechenden Platzhalter eingefügt. Das Ergebnis lautet also:

Dies ist ein sinnloser Text mit drei Platzhaltnern, der als Beispiel dient. 

Das kann man sich zunutze machen, um Texte einfach mit beliebigen Zeichen zu umschliessen: 

'{1}{0}{1}' -f 'Eingabe',"`'"

Logischerweise kann man das auch in der Pipeline nutzen, um z.B. Daten aus einer Textdatei zu umschliessen, oder im folgenden Beispiel einfach für ein paar Zahlen:

1..10 | foreach-object { '{1}{0}{1}' -f $_,"`'" }

'1'
'2'
'3'
'4'
'5'
'6'
'7'
'8'
'9'
'10'

Jetzt wäre es noch schön, wenn wir den Text nicht als einzelzeichen bekommen würden, sondern Komma-separiert. Hierfür ist der -join Operator sehr hilfreich, der einfach mehrere Eingaben mit einem Trennzeichen zusammenfügt. Um den join-Operator nutzen zu können, muß die Eingabeliste aber erst mal vollständig erzeugt werden. Daher speichern wir die vorige Ausgabe erst in ein Array und fügen die Werte anschliessend zusammen:

$Zahlenarray = 1..10 | foreach-object { '{1}{0}{1}' -f $_,"`'" }
$zahlenarray -join ','

Alternativ können wir das Ergebnis auch in einer Zeile erzeugen:

( 1..10 | foreach-object { '{1}{0}{1}' -f $_,"`'" }) -join ','

Update, 25.05-2016

Und hier eine kleine Funktion, die das Umschliessen von selbst erledigt und auch öffnende Klammern schliessen kann:

#requires -Version 2
<#
.Synopsis
This function can enclose a String with a given Character. It can be used in the Pipeline.
.DESCRIPTION
The purpose of this function is to enclose a string into a Quote-Character. This is especially helpful
if you need to export text into a csv-File and need a Text-Qualifier.
.EXAMPLE
Set-Quote -Inputstring "This is a fine text"

Enclose the Inputstring in single qoutes
.EXAMPLE
get-service | Select-Object -ExpandProperty DisplayName | set-quote -quotecharacter "!"

Encloses the Service-Names in an exclamation-mark
.EXAMPLE
get-service | Select-Object -ExpandProperty DisplayName | set-quote -quotecharacter "(" -surroundingBrackets

Encloses the Service-Names in opening and closing Brackets. Works with "(","{" and "[".
.EXAMPLE
Get-EventLog -LogName Application -EntryType Error | Select-Object TimeWritten, @{ name="Message"; expression={ set-quote -inputstring $_.Message -quotecharacter '"' }}

Takes all Errors from the Event-Log and sorrounds each message with a double Quote
#>
function Set-Quote
{
[cmdletbinding()]
param (
   [parameter(mandatory = $true,
              ValueFromPipeline = $true)]
   [string]$inputstring,

   [string]$quotecharacter = '''',

   [switch]$surroundingBrackets
)

begin {
   If ( $surroundingBrackets )
   {
      Switch ($quotecharacter)
      {
         '{' { $openingQuote = $quotecharacter; $closingQuote = '}'; break }
         '[' { $openingQuote = $quotecharacter; $closingQuote = ']'; break }
         '(' { $openingQuote = $quotecharacter; $closingQuote = ')'; break }

        }
   }
   Else { $openingQuote = $quotecharacter; $closingQuote = $quotecharacter }
   }

process {
  '{0}{1}{2}' -f $openingQuote, $inputstring, $closingQuote
  }
}

Kommentare hinterlassen