Подтвердить что ты не робот

PowerShell и StringBuilder

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

Я использую System.Text.StringBuilder в PowerShell script. script заключается в том, что

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

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

4b9b3361

Ответ 1

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

[void]$sb.Append($c)

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

Ответ 2

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

PowerShell - это script язык, используемый не программистами-разработчиками, такими как администраторы. Вы являетесь разработчиком С# со всеми своими знаниями, но вы можете написать то, что хотите написать проще. В 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

  • foreach не выполняет итерацию по символам в строке, она рассматривает его как отдельный элемент. Так что нам нужно передать строку в [char[]] (или использовать $line.GetEnumerator()).

  • Выражение $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