我的google-fu再次失败了。信息(可能)在那里,但我找不到它。我知道UNIX就像我的手背,使用cygwin等。然而随着Powershell在服务器上的可用性增加,以及(至少在生产服务器上)使cygwin到位的困难,我试图拿起Powershell。如果不出意外,这是我军火库中的另一种武器。
基本上,我正在寻找与awk命令相同的Powershell:
awk '$9 == "503" { print $0 }' < access_log
对于那些不知道awk的人,这基本上是比较输入文件的字段9,然后执行块(这是一个apache访问日志,所以它返回来自access_log的所有行,其中HTTP状态代码返回是503)。 Awk自动处理基于空格的文件分割。 0美元是整条生产线(未经批准),单个字段分为1美元,2美元,...... [等]。
我知道我可以像这样使用拆分:
cat access_log | %{ $_.split() }
将传入的行拆分为数组,但是我无法从这里解决如何使用select-object
或where-object
根据给定字段选择(和输出)整行。< / p>
另一种选择是select-string
,但我似乎无法通过%{ $_.split()[8] -eq "503" }
的方式传递表达式。 (我注意到PowerShell是从零开始的,因此查看字段8)。
我不确定我是否遗漏了一些明显的东西,而且我找不到合适的google-fu来给我提供信息(所以如果这是某个地方的骗局就不会感到惊讶。)
为任何帮助干杯: - )
答案 0 :(得分:3)
是的,在这种情况下where-object(别名?)更好:
cat access_log | ?{($_ -split '\s+',0,'regexmatch')[8] -eq 503}
请注意,.NET split方法将为连续空格创建空字符串条目,因此我在PowerShell 2.0中使用-split运算符来避免这种情况。
我的正则表达式在这方面很弱但我想有一种方法可以使用正则表达式来获得第9个字段(比下面的脑死亡方法更容易 - 任何人?):
根据约翰内斯的评论更新了正则表达式模式:
cat access_log | Select-String '^\s*(?:\w+\s+){8}503'
答案 1 :(得分:2)
找到了答案 - 虽然仍然很高兴看到是否有其他方法可以做到这一点[所以我会留下几天没有答案,看看是否有别人有替代方法]。我发现的方法是:
cat access_log | where-object { $_.split()[8] -eq "503" }
可以缩写为:
cat access_log | where { $_.split()[8] -eq 503 }
所以这是一个让事情按正确的顺序进行的案例。我最初是沿着正确的路线行进,但是在路上贴了太多的管道。
答案 2 :(得分:0)
根据您发布的代码我理解,您正在寻找第9个字段为'503'的行,然后写出这些行的第1个字段?如果是这样的话:
Get-Content -Path "access_log" | ForEach-Object {
if ($_ -match '(?<Field0>\d+)\s(?:\d+\s){7}503')
{
Write-Host $Matches["Field0"]
}
}
修改强>
使用Select-String
的示例(比我之前的更好):
Select-String -Path "access_log" -Pattern '(?<Field0>\d+)\s(?:\d+\s){7}503' | ForEach-Object {
Write-Host $_.Matches[0].Groups["Field0"]
}