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
Я сделал что-то не так?
Ответы
Ответ 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