PowerShell и StringBuilder - PullRequest
       4

PowerShell и StringBuilder

32 голосов
/ 18 октября 2011

Я новичок в PowerShell, но знаком с классами .NET.

Я использую System.Text.StringBuilder в скрипте PowerShell. Сценарий в том, что

Function MyStringFunc([String]$line) {
    $r = New-Object -TypeName "System.Collections.Generic.List``1[[System.String]]";
    $sb = New-Object -TypeName "System.Text.StringBuilder";

    foreach ($c in $line) {
        $sb.Append($c);
        $r.Add($sb.ToString());
    }

    return $r;
}

$line1 = "123";
$a = MyStringFunc $line1;
$a

Я ожидал, что результат будет

1
12
123

Однако результат

                  Capacity                MaxCapacity                    Length
                  --------                -----------                    ------
                        16                 2147483647                         3
123

Я сделал что-то не так?

Ответы [ 3 ]

41 голосов
/ 18 октября 2011

Некоторые методы в StringBuilder, такие как Append IIRC, возвращают StringBuilder, чтобы вы могли вызывать больше методов StringBuilder.Однако PowerShell работает так, что он выводит все результаты (возвращаемые значения в случае вызовов метода .NET).В этом случае приведите результат к [void], чтобы игнорировать возвращаемое значение, например:

[void]$sb.Append($c)

Обратите внимание, что вам не нужно заканчивать строки в ; в PowerShell.Однако если вы поместите несколько команд в одну строку, используйте ; 'для разделения этих команд.

4 голосов
/ 18 октября 2011

Потому что вы говорите, что вы новичок в PowerShell.Мой ответ немного подробнее о том, как вы пишете PowerShell.

PowerShell - это язык сценариев, он используется не программистами-разработчиками, такими как администраторы.Вы - разработчик C # со всеми своими знаниями, но вы можете написать то, что хотите написать, проще.В PowerShell существует синтаксис для использования списков и Hastables, попробуйте следующее:

$a = @()
$a += "Bonjour"
$a += "Salut"
$a
$a | get-member
Get-Member -InputObject $a

$rwc = @{}
$rwc += @{1="Blues"}
$rwc += @{2="Blacks"}
$rwc
$rwc | get-member
Get-Member -InputObject $rwc

Вот три функции, выполняющие одно и то же, я знаю, что строители строк немного эффективнее в памяти, но в этомзаботы.

Function MyStringFunc([String]$line)
{ 
  $r = New-Object -TypeName "System.Collections.Generic.List``1[[System.String]]"; 
  $sb = New-Object -TypeName "System.Text.StringBuilder"; 

  foreach ($c in [Char[]]$line)
  { 
    $a = $sb.Append($c); 
    $r.Add($sb.ToString()); 
  }  
  return $r; 
} 

# A more simple way
Function MoreReadableStringFunction([String]$line)
{
  $r = @() # an untyped list

  foreach ($c in [Char[]]$line)
  { 
    $a += $c; 
    $r += $a;
  } 
  return $r;
}

# More simple but not so readable
Function MoreSimpleStringFunction([String]$line)
{
  $r = @() # an untyped list

  [Char[]]$line | % {$a += $_; $r += $a} 
  return $r;
}


Clear-Host
$line1 = "123";

$t1 = MyStringFunc $line1; 
$t1

$t2 = MoreReadableStringFunction $line1
$t2

$t3 = MoreSimpleStringFunction $line1
$t3
3 голосов
/ 18 октября 2011
  1. foreach не перебирает символы в строке, он обрабатывает его как один элемент. Так что нам нужно привести строку к [char[]] (или использовать $line.GetEnumerator()).

  2. Выражение $sb.Append($c) получает экземпляр компоновщика. В PowerShell это записывается в вывод. Насколько это нежелательно, мы должны подавить этот вывод ($null = ... или ... > $null или ... | Out-Null).

Ожидаемый результат получается с помощью этого кода:

Function MyStringFunc([String]$line) {
    $r = New-Object -TypeName "System.Collections.Generic.List``1[[System.String]]";
    $sb = New-Object -TypeName "System.Text.StringBuilder";

    foreach ($c in [char[]]$line) {
        $null = $sb.Append($c);
        $r.Add($sb.ToString());
    }

    return $r;
}

$line1 = "123";
$a = MyStringFunc $line1;
$a
...