Formatlamayla Cuma Eğlencesi
PowerShell, ağınızdaki bilgisayar sistemlerinden her türlü bilgiyi alma konusunda oldukça ustadır. Çoğu zaman veriler bir bakışta anlaşılması zor bir formattadır. Örneğin 1202716672 gibi bir değer gördüğünüzde bu MB cinsinden mi yoksa GB cinsinden mi? Bu değeri KB olarak görmeniz gerekirse ne olur? Seni bilmem ama ben bu dönüşümleri kafamda ve anında yapma konusunda iyi değilim. Bunun yerine sıklıkla bunun gibi komutlara başvuruyoruz.
PS C:\> get-ciminstance win32_computersystem | select Name,Number*,@{Name="MemGB";Expression={$_.totalphysicalmemory/1gb -as [int]}},Manufacturer
Name : WIN81-ENT-01
NumberOfLogicalProcessors : 4
NumberOfProcessors : 1
MemGB : 8
Manufacturer : LENOVOBu, 8589934592 değerini görmekten çok daha kolaydır. Aynı şey yüzdelerin hesaplanmasında da geçerlidir. Yine Select-Object ile özel karma tabloları kullanmaya geri döndük. Elbette daha da ileri gidebilir ve özel format ve yazı tipi uzantıları oluşturabilirsiniz. Ama bazen, en azından kendi adıma konuşursak, arada bir şey istersiniz. Böylece Format-Value ve Format-Percent olmak üzere iki fonksiyon oluşturdum ve bunları bir modül olarak paketledim.
Function Format-Percent {
<#
.Synopsis
Calculate a percent
.Description
This command calculates a percentage of a value from a total, with the formula (value/total)*100. The default is to return a value to 2 decimal places but you can configure that with -Decimal. There is also an option to format the percentage as a string which will include the % symbol.
.Parameter Value
The numerator value. The parameter has aliases of X and Numerator.
.Parameter Total
The denominator value. The parameter has aliases of Y and Denominator.
.Parameter Decimal
The number of decimal places to return between 0 and 15.
.Parameter String
Format the percentage as a string which will include the % symbol. This is done using the -f operator.
.Example
PS C:\> Format-Percent 1234 5000
24.68
.Example
PS C:\> get-ciminstance win32_operatingsystem -computer chi-dc04 | select PSComputername,TotalVisibleMemorySize,@{Name="PctFreeMem";Expression={ Format-Percent $_.FreePhysicalMemory $_.TotalVisibleMemorySize }}
PSComputerName TotalVisibleMemorySize PctFreeMem
-------------- ---------------------- ----------
chi-dc04 1738292 23.92
.Example
PS C:\> get-ciminstance win32_operatingsystem -computer chi-dc04 | select PSComputername,TotalVisibleMemorySize,@{Name="PctFreeMem";Expression={ Format-Percent $_.FreePhysicalMemory $_.TotalVisibleMemorySize -asString }}
PSComputerName TotalVisibleMemorySize PctFreeMem
-------------- ---------------------- ----------
chi-dc04 1738292 23.92%
.Notes
Last Updated: May 30, 2014
Version : 1.0
#>
[cmdletbinding(DefaultParameterSetName="None")]
Param(
[Parameter(Position=0,Mandatory,HelpMessage="What is the value?")]
[ValidateNotNullorEmpty()]
[Alias("X","Numerator")]
$Value,
[Parameter(Position=1,Mandatory,HelpMessage="What is the total value?")]
[ValidateNotNullorEmpty()]
[Alias("Y","Denominator")]
$Total,
[ValidateNotNullorEmpty()]
[ValidateRange(0,15)]
[int]$Decimal=2,
[Parameter(ParameterSetName="String")]
[Switch]$AsString
)
Write-Verbose "Calculating percentage from $Value/$Total to $decimal places"
$result = $Value/$Total
if ($AsString) {
Write-Verbose "Writing string result"
$pctstring = "{0:p$Decimal}" -f $result
#remove the space before the % symbol
$pctstring.Replace(" ","")
}
else {
Write-Verbose "Writing numeric result"
[math]::Round( ($result*100),$Decimal)
}
} #end function
Function Format-Value {
<#
.Synopsis
Format a numeric value
.Description
This command will format a given numeric value. By default it will treat the number as an integer. Or you can specify a certain number of decimal places. The command will also allow you to format the value in KB, MB, etc. Or you can let the command autodetect the value and divide by an appropriate value.
.Parameter Unit
The unit of measurement for your value. Valid choices are "KB","MB","GB","TB", and "PB". If you don't specify a unit, the value will remain as is, although you can still specify the number of decimal places.
.Parameter Decimal
The number of decimal places to return between 0 and 15.
.Example
PS C:\> Get-CimInstance -class win32_logicaldisk -filter "DriveType=3" | Select DeviceID,@{Name="SizeGB";Expression={$_.size | format-value -unit GB}},@{Name="FreeGB";Expression={$_.freespace | format-value -unit GB -decimal 2}}
DeviceID SizeGB FreeGB
-------- ------ ------
C: 200 124.97
D: 437 29.01
E: 25 9.67
.Example
PS C:\> (get-process chrome | measure ws -sum ).sum | format-value -Autodetect -verbose -Decimal 4
VERBOSE: Formatting 1180504064
VERBOSE: Using Autodetect
VERBOSE: ..as GB
VERBOSE: Reformatting 1.09943008422852
VERBOSE: ..to 4 decimal places
1.0994
.Notes
Last Updated: 5/29/2014
Version : 1.0
#>
[cmdletbinding(DefaultParameterSetName="Default")]
Param(
[Parameter(Position=1,Mandatory,ValueFromPipeline)]
[ValidateNotNullorEmpty()]
$InputObject,
[Parameter(Position=0,ParameterSetName="Default")]
[ValidateSet("KB","MB","GB","TB","PB")]
[string]$Unit,
[ValidateRange(0,15)]
[int]$Decimal,
[Parameter(ParameterSetName="Auto")]
[switch]$Autodetect
)
Process {
Write-Verbose "Formatting $Inputobject"
if ($PSCmdlet.ParameterSetName -EQ "Default") {
Write-Verbose "..as $Unit"
Switch ($Unit) {
"KB" { $value = $Inputobject / 1KB ; break }
"MB" { $value = $Inputobject / 1MB ; break }
"GB" { $value = $Inputobject / 1GB ; break }
"TB" { $value = $Inputobject / 1TB ; break }
"PB" { $value = $Inputobject / 1PB ; break }
default {
#just use the raw value
$value = $Inputobject
}
} #switch
}
else {
Write-Verbose "Using Autodetect"
if ($InputObject -ge 1PB) {
Write-Verbose "..as PB"
$value = $Inputobject / 1PB
}
elseif ($InputObject -ge 1TB) {
Write-Verbose "..as TB"
$value = $Inputobject / 1TB
}
elseif ($InputObject -ge 1GB) {
Write-Verbose "..as GB"
$value = $Inputobject / 1GB
}
elseif ($InputObject -ge 1MB) {
Write-Verbose "..as MB"
$value = $Inputobject / 1MB
}
elseif ($InputObject -ge 1KB) {
Write-Verbose "..as KB"
$value = $Inputobject / 1KB
}
else {
Write-Verbose "..as bytes"
$value = $InputObject
}
}
Write-Verbose "Reformatting $value"
if ($decimal) {
Write-Verbose "..to $decimal decimal places"
[math]::Round($value,$decimal)
}
else {
Write-verbose "..as [int]"
$value -as [int]
}
} #process
}
Set-Alias -Name fv -Value Format-Value
Set-Alias -Name fp -value Format-Percent
Export-ModuleMember -Function * -Alias *Format-Value herhangi bir değeri alır ve varsayılan olarak onu bir tamsayıya yuvarlar. Veya değerin GB veya MB gibi belirli bir ölçü birimi olarak biçimlendirilmesini belirtebilirsiniz. Ondalık basamak sayısını bile belirleyebilirsiniz. Veya -Autodetect parametresini kullanabilirsiniz; işlev, değerinizin 'boyutu' hakkında en iyi tahminde bulunacaktır. Hangi birimi algıladığını bilmek istiyorsanız -Verbose kullanın.
Yüzdelerle de benzer bir şey yaptım. Tek yapmanız gereken bir değer ve toplam belirtmektir, gerisini işlev halleder. Yine ondalık basamak sayısını belirleyebilirsiniz. Varsayılan olarak, işlev boru hattına sayısal bir değer yazar; bence sıralamak istiyorsanız bunu kolaylaştırır. Ancak -f operatörünü kullanacak bir dize olarak yüzde almayı da belirtebilirsiniz. Dize % sembolünü içerecektir. Değer ile sembol arasındaki boşluğu kaldırmak için fazladan bir adım atıyorum.
Fonksiyonla birlikte PowerShell ifadelerimin yazılması biraz daha kolaylaşıyor.
Get-CimInstance -class win32_logicaldisk -filter "DriveType=3" |
Select DeviceID,
@{Name="SizeGB";Expression={$_.size | fv -unit GB}},
@{Name="FreeGB";Expression={$_.freespace | fv -unit GB -decimal 2}},
@{Name="PctFree";Expression={fp -x $_.freespace -y $_.size}}
Kod örneğinde işlev ve parametre takma adlarını kullanıyorum. Ama sonucu beğendim.
FormatFunctions.zip dosyasını indirip modüller dizininize çıkarın ve hazır olun. Minimum PowerShell sürümünü 3.0 olarak ayarladım, ancak bu komutların v2'de çalışmasını engelleyecek hiçbir şey düşünemiyorum. Ama yine de seni en az 3'e götürmek isterim.
Umarım ne düşündüğünüzü ve modüle başka hangi tür veri formatlarının eklenmesini istediğinizi bana bildirirsiniz.
NOT: http://bit.ly/1PzSnJa adresinde bir güncelleme yayınlanmıştır.
