我有一个处理所有SQL Server的脚本。该脚本有几个函数,我有一个错误例程,它将服务器名称,函数名称和错误消息记录到500行x 3列数组中。在脚本结束时,我想将此数组排序为服务器名称序列。有几篇文章建议我需要做的就是将数组传递给sort-object
cmdlet,但是当我这样做时,我的数组的每个元素都被system.Object[]
替换。 NB。在函数之前填充的数组只是我的数组的一个例子
$global:ErrorCount = 0
$global:ErrArray = new-object 'object[,]' 500,3
$global:ErrArray[1,00]= "SV000004"
$global:ErrArray[1,01]= "ProcessServers"
$global:ErrArray[1,02]= "The server was not found or was not accessible."
$global:ErrArray[2,00]= "BOSWEB02"
$global:ErrArray[2,01]= "GetDatabases"
$global:ErrArray[2,02]= "Database Status = Shutdown"
$global:ErrArray[3,00]= "SATURN"
$global:ErrArray[3,01]= "GetDatabases"
$global:ErrArray[3,02]= "Database Status = Shutdown"
$global:ErrArray[4,00]= "BOSWEB02"
$global:ErrArray[4,01]= "GetSystemInfo"
$global:ErrArray[4,02]= "Access is denied"
$global:ErrorCount = 4
Function DisplayErrors
{
Write-Host "`nBefore:-`n"
for ( $iLoop=1; $iLoop -le $global:ErrorCount; $iLoop++)
{
"{0,-14} {1,-18} {2,-80}" -f
$global:ErrArray[$iLoop,0], $global:ErrArray[$iLoop,1],
$global:ErrArray[$iLoop,2]
}
$Sorted = $global:ErrArray | Sort-Object @{Expression={$_[0]}}
Write-Host "`nAfter:-`n"
for ( $iLoop=1; $iLoop -le $global:ErrorCount; $iLoop++)
{
"{0,-14} {1,-18} {2,-80}" -f
$Sorted[$iLoop,0], $Sorted[$iLoop,1], $Sorted[$iLoop,2]
}
}
DisplayErrors
输出如下: -
在: -
SV000004 ProcessServers The server was not found or was not accessible.
BOSWEB02 GetDatabases Database Status = Shutdown
SATURN GetDatabases Database Status = Shutdown
BOSWEB02 GetSystemInfo Access is denied
在: -
System.Object[] System.Object[] System.Object[]
System.Object[] System.Object[] System.Object[]
System.Object[] System.Object[] System.Object[]
System.Object[] System.Object[] System.Object[]
有谁能告诉我这里我做错了什么?
非常感谢: - )
答案 0 :(得分:1)
以这种方式创建数组(锯齿状数组:array [] [])sort-object
可以正常工作:
$global:ErrArray += ,@("SV000004","ProcessServers","The server was not found or was not accessible.")
$global:ErrArray += ,@("BOSWEB02","GetDatabases","Database Status = Shutdown")
$global:ErrArray += ,@("SATURN","GetDatabases","Database Status = Shutdown")
$global:ErrArray += ,@("BOSWEB02","GetSystemInfo","Access is denied" )
Function DisplayErrors
{
Write-Host "`nBefore:-`n"
foreach ( $server in $global:Errarray)
{
write-host $server
}
$sorted = $global:ErrArray | Sort-Object @{Expression={$_[0]}}
Write-Host "`nAfter:-`n"
foreach ( $server in $sorted)
{
write-host $server
}
}
DisplayErrors
或更像您的代码:
$global:ErrArray += ,@("SV000004","ProcessServers","The server was not found or was not accessible.")
$global:ErrArray += ,@("BOSWEB02","GetDatabases","Database Status = Shutdown")
$global:ErrArray += ,@("SATURN","GetDatabases","Database Status = Shutdown")
$global:ErrArray += ,@("BOSWEB02","GetSystemInfo","Access is denied" )
Function DisplayErrors
{
Write-Host "`nBefore:-`n"
for ( $iLoop=0; $iLoop -lt $global:errarray.count; $iLoop++)
{
"{0,-14} {1,-18} {2,-80}" -f $global:ErrArray[$iLoop][0], $global:ErrArray[$iLoop][1], $global:ErrArray[$iLoop][2]
}
$sorted = $global:ErrArray | Sort-Object @{Expression={$_[0]}}
Write-Host "`nAfter:-`n"
for ( $iLoop=0; $iLoop -lt $sorted.count; $iLoop++)
{
"{0,-14} {1,-18} {2,-80}" -f $Sorted[$iLoop][0], $Sorted[$iLoop][1], $Sorted[$iLoop][2]
}
}
DisplayErrors
答案 1 :(得分:0)
Whlist我不知道为什么Powershell会破坏阵列,我可能会有更多的Powershellish解决方案。让我们创建一个包含数据和一维数组的自定义对象。排序很简单。
# Custom error object
function CreateErrorObject {
param ([string]$server, [string]$proc, [string]$message)
$objError = New-Object System.Object
$objError | Add-Member -type NoteProperty -name Server -value $server
$objError | Add-Member -type NoteProperty -name Proc -value $proc
$objError | Add-Member -type NoteProperty -name Message -value $message
$objError
}
$errors = @() # Empty array
# Populate error objects some way
$errors += CreateErrorObject "SV000004" "ProcessServers" "The server was not found or was not accessible"
$errors += CreateErrorObject "BOSWEB02" "GetDatabases" "Database Status = Shutdown"
$errors += CreateErrorObject "SATURN" "GetDatabases" "Database Status = Shutdown"
$errors += CreateErrorObject "BOSWEB02" "GetSystemInfo" "Access is denied"
$errors # Unsorted list
$errors | sort -Property server # sort by server property
$errors | sort -Property proc # sort by proc property
$errors | sort -Property message # sort by message property
答案 2 :(得分:0)
我在实现中将ErrArray更改为0 -
$ global:ErrArray [ 0 ,00] =“SV000004”
...但是否则插入以下功能,交易线......
$Sorted = $global:ErrArray | Sort-Object @{Expression={$_[0]}}
... for ...
$Sorted = Order-2dArray $global:ErrArray;
# Naming sorts stinks: http://stackoverflow.com/questions/27173621/
# NOTE: **EVERY** array entry in [0,x] must be non-null if -ColCount not set.
# NOTE: **EVERY** array entry in [y,0] must be non-null. Thanks.
Function Order-2dArray
{
param
(
[Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true)]
$ArrayToSort,
[int]$ColCount = -1, # I hate multi-dim PS arrays.
[int]$SortColumn = 0, # Would be a touch faster if this were a constant.
[switch][alias("desc")]$Descending # Ascend by default.
)
$fullCount = $ArrayToSort.Length;
if ($ColCount -le 0) # if not given, guess by checking for $nulls.
{
$ColCount=0;while ($ArrayToSort[0,$ColCount] -ne $null) {
$ColCount++;
}
}
$RowCount = $fullCount / $ColCount;
$nullRowCap = $RowCount-1; # 1-based to 0-based
while ($ArrayToSort[$nullRowCap,0] -eq $null) { $nullRowCap--; }
$itemToPlace = $nullRowCap;
for ($i=0;$i -lt $nullRowCap;$i++)
{
for ($j=0;$j -lt $itemToPlace;$j++)
{
# This dual-check method for optionally descending is not efficient.
if (($ArrayToSort[$j,$SortColumn] -gt $ArrayToSort[($j+1),$SortColumn] -and !$Descending) -or
($ArrayToSort[$j,$SortColumn] -lt $ArrayToSort[($j+1),$SortColumn] -and $Descending))
{
for($k=0;$k -lt $ColCount;$k++) {
$hold = $ArrayToSort[$j,$k];
$ArrayToSort[$j,$k] = $ArrayToSort[($j+1),$k];
$ArrayToSort[($j+1),$k] = $hold;
}
}
}
$itemToPlace--;
}
Write-Host -BackgroundColor Magenta $ArrayToSort.GetType();
, $ArrayToSort; # see http://stackoverflow.com/questions/7833317/ for comma use
}
[意识到这是一个僵尸问题 - ]这对于评论来说有点太大了,所以我将创建一个答案来解释为什么你需要使用@CB。或@vonPryz建议。
首先,请看结尾处的评论。在PowerShell 1.0中,OP的方法可以起作用。显然不是现在。
简而言之,您无法再访问PowerShell中的“二维数组第一行中的值”。如果要将条目的每个“行”分组到对象中并将该数组传递给Sort-Object
,则需要有对象数组。因此,您可以选择数组,如CB。的答案,或 New-Object
个数组,就像在vonPryz中一样 - 或者其他任何感觉最好。但它必须是X 的数组,而不是二维数组。
要显示内容,请尝试
PS> $global:ErrArray[0]
......在任何时候。你会得到......
You cannot index into a 2 dimensional array with index [0].
At line:1 char:1
+ $global:ErrArray[0]
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NeedMultidimensionalIndex
也就是说,没有$ global:ErrArray [0]返回三个值,至少不是你想象的那样。数组的第一个维度不会对第二个维度中的三个对象进行分组。 它更像1500个地址而不是500个楼层,每个地址有三个地址。
在您的代码中尝试此操作以确认它为什么不会抛出错误:
$Sorted = $global:ErrArray | Sort-Object @{
Expression={
$_[0];
Write-Host $_[0];
}
}
结果可能会让你感到惊讶 - 这是每个字符串的第一个字符。
S
P
T
B
G
D
S
G
D
B
G
A
由于没有“多维数组的单行”概念,PowerShell会将二维数组中的所有条目解压缩为字符串的单维数组,并使用{ {1}},你正在抓取字符串中的第一个字符作为数组。 ! (如果你在每个点上都有整数而不是字符串,我相信这些代码会在这里打破。)
这意味着您不只是从二维数组中的任何位置对所有非空值进行排序,而只是按每个位置的第一个字母排序!
$_[0]
之所以有效,是因为(并且我同意这非常违反直觉)PowerShell会在现在的单维$Sorted[$iLoop,0]
中为您提供$iLoop
- 和0
个值阵列。它认为你为新的扁平数组传递两个索引,返回的值是一个包含这两个值的数组。
尝试使用这两行代替$Sorted
一行:
-f
第一个“有效” - 它为"{0} {1}" -f $Sorted[$iLoop,0]
"{0} {1}" -f $Sorted[$iLoop,0], $Sorted[$iLoop,1], $Sorted[$iLoop,2]
提供了$iLoop
$Sorted
的{{1}}和{0}
的第0个值,因为您基本上传递了两个字符串。它们可能已作为数组传入,但PowerShell“帮助”将其解压缩为两个字符串。完美,有点。
第二行返回到你看到的{1}
,因为它是......一个由三个数组组成的数组(因为它认为你使用的是数组逗号表示法:System.Object[]
),每个长度为2(从它认为从X,Y,Z
看到的两个索引,等等)。在这种情况下,数组中的前两个元素被推入$iLoop, 0
和{0}
,隐式调用{1}
,并变为ToString()
。
当我们有像System.Object[]
之类的东西时,我们确认它正在返回数组。在这里,我正在使用PowerGUI并在排序之后删除一个断点来调试:
$Sorted[$iLoop,0]
因此,您要向格式调用中发送三个[DBG]: PS> $t2 = $Sorted[$iLoop,0], $Sorted[$iLoop,1], $Sorted[$iLoop,2]
[DBG]: PS> $t2.Length
3
[DBG]: PS> $t2[0]
BOSWEB02
BOSWEB02
[DBG]: PS> $t2[0][0]
BOSWEB02
数组,其中包含两个字符串。在Object[]
上调用ToString()
可以获得令人讨厌的System.Object []。
如果你想按照每个第一维第二维的第0个元素中的内容对二维数组进行排序[原文如此],你可能不得不把它写成旧式,泡泡或者Quicksort或者什么 - 有你,就像我在这个答案的第一部分所做的那样。 (如果可以的话,最好使用CB。建议,我认为。)
所以这一切都有道理。对于PowerShell,您有1500个地址,但没有按“Object[]
”值对它们进行实际分组。别担心,它对我来说也没有立竿见影(因此我对这个问题感到磕磕绊绊)。
编辑:为了让事情更有趣,看来数组 正如您在PowerShell v1.0中所期望的那样工作:http://arstechnica.com/civis/viewtopic.php?t=52603但是看看脚本是如何工作的Guy在2011年已经doing arrays of arrays for multiple dimensions。