我刚开始使用Powershell,这是我的第一个脚本。
我正在检查日志文件的后50行中的3个字符串。我需要找到所有三个字符串,如果缺少其中任何一个,则会显示错误消息。我已经编写了以下脚本,但它没有给我预期的结果。
(Get-Content C:\foo\bar.log )[-1..-50] | Out-File C:\boom\shiva\log.txt
$PO1 = Get-Content C:\boom\shiva\log.txt | where {$_ -match "<Ping:AD_P01_RCV> ok"}
$PO2 = Get-Content C:\boom\shiva\log.txt | where {$_ -match "<Ping:AD_P02_SND> ok"}
$PO3 = Get-Content C:\boom\shiva\log.txt | where {$_ -match "<Ping:AD_P03_RCV> ok"}
我对以上代码感到满意。问题出在下面。我不想使用if-else三次。我正在努力起草一个for循环,该循环可以节省空间,但仍然给我相同的结果。
if (!$PO1)
{
"PO1 is critical"
}
else
{
"PO1 is OK"
}
if (!$PO2)
{
"PO2 is critical"
}
else
{
"PO2 is OK"
}
if (!$PO3)
{
"PO3 is critical"
}
else
{
"PO3 is OK"
}
有人可以给我一个小例子,说明我如何将这3个if-else放入一个for循环中。
答案 0 :(得分:4)
如果您只想找出所有3个字符串都存在,则此脚本还将显示缺少的三个字符串。
(二进制编码在变量$ Cnt中)
## Q:\Test\2018\07\13\SO_51323760.ps1
##
$Last50 = Get-Content 'C:\foo\bar.log' | Select-Object -Last 50
$Cnt = 0
if ($Last50 -match "<Ping:AD_P01_RCV> ok"){$Cnt++}
if ($Last50 -match "<Ping:AD_P02_SND> ok"){$Cnt+=2}
if ($Last50 -match "<Ping:AD_P03_RCV> ok"){$Cnt+=4}
if ($cnt -eq 7){
"did find all 3 strings "
} else {
"didn't find all 3 strings ({0})" -f $cnt
}
Variant立即抱怨缺少P0(1..3)
$Last50 = Get-Content 'C:\foo\bar.log' | Select-Object -Last 50
if (!($Last50 -match "<Ping:AD_P01_RCV> ok")) {"PO1 is critical"}
if (!($Last50 -match "<Ping:AD_P02_SND> ok")) {"PO2 is critical"}
if (!($Last50 -match "<Ping:AD_P03_RCV> ok")) {"PO3 is critical"}
抱歉,这个星期一我有点慢。
要通过构建变量名称在循环中检查不同的变量,请执行以下操作:
1..3| ForEach-Object {
If (!(Get-Variable -name "P0$_").Value){"`$P0$_ is critical"}
}
答案 1 :(得分:1)
使用哈希表比使用单独命名的变量可以更好地解决您要执行的操作。
Sub Parent_sub()
Dim v1 As Integer,v2 As Integer,v3 as Integer
v1 = 0
v2 = -1
v3 = -2
Child_sub v1, v2, v3
msgbox "the variables are " & v1 & " ," & v2 & ", and " & v3
End Sub
Sub Child_sub(ByRef c1 as Integer, ByRef c2 as Integer, ByRef c3 as
Integer)
c1 = 3
c2 = 4
c3 = 5
End Sub
您可以检查所有行是否至少出现一次,如下所示:
$data = Get-Content 'C:\boom\shiva\log.txt'
$ht = @{}
1..3 | ForEach-Object {
$key = 'P{0:d2}' -f $_
$str = if ($_ -eq 2) {"${key}_SND"} else {"${key}_RCV"}
$ht[$key] = $data -match "<ing:AD_${str}> ok"
}
$ht.Keys | ForEach-Object {
if ($ht[$_]) {
"${key} found in log."
} else {
"${key} not found in log."
}
}
答案 2 :(得分:0)
PSv3在-Tail
中引入了-Last
(Get-Content
)参数,这是从 end 中提取固定行数的最有效方法一个文件。
您可以将其输出通过管道传递到Select-String
,后者接受正则表达式模式的数组,其中任何一个都会产生匹配项(隐式OR逻辑)。
$matchingLines = Get-Content -Tail 50 C:\foo\bar.log |
Select-String '<Ping:AD_P01_RCV> ok', '<Ping:AD_P02_SND> ok', '<Ping:AD_P03_RCV> ok'
if ($matchingLines) { # at least 1 of the regexes matched
$matchingLines.Line # output the matching lines
} else { # nothing matched
Write-Warning "Nothing matched."
}
答案 3 :(得分:0)
我终于得到了草稿,该草稿解决了我的查询以通过for循环循环变量。最后,我不得不将这些单独的变量转换为数组。但是,htis给了我预期的结果。基本上,我需要此脚本来向Nagios插件提供输入,该插件需要进行少量修改但已完成。
(Get-Content C:\foo\bar.log )[-1..-50] | Out-File C:\boom\shiva\log.txt
$j = 1
$PO = new-object object[] 3
$PO[0] = Get-Content C:\boom\shiva\log.txt | where {$_ -match "<Ping:AD_P01_RCV> ok"}
$PO[1] = Get-Content C:\boom\shiva\log.txt | where {$_ -match "<Ping:AD_P02_SND> ok"}
$PO[2] = Get-Content C:\boom\shiva\log.txt | where {$_ -match "<Ping:AD_P03_RCV> ok"}
foreach( $i in $PO){
if (!$i){
"PO "+$j+" is CRITICAL"}
else{
"PO "+$j+" is OK"}
$j+=1
}
感谢LotPings,Ansgar和mklement0的支持和回应。我从你的答案中得到了一些东西。