【问题标题】:Exclude records in CSV file based on exclusion criteria in Config file using PowerShell使用 PowerShell 根据 Config 文件中的排除条件排除 CSV 文件中的记录
【发布时间】:2020-11-19 03:13:52
【问题描述】:

我正在处理的用例是从命令提示符中提取为特定应用程序(例如 Tableau 等)运行的服务列表的详细信息。输出通常采用以下格式

Tableau 服务中的文件内容

'Service 0' is running
'Service 1' is running
'Service 2' is running
'Service 3' is running
'Service 4' is running
'Test Service 5' is stopped
'SAML Service 6' is stopped
'Database Service 7' is stopped
'Tableau Service 8' is stopped
'Service 9' is running
'Service 10' is running
'Service 11' is running
'Service 12' is stopped
'Service 13' is running
'Service 14' is running
'Service 15' is stopped

最终的结果应该是已经停止的服务列表

Service 12
Service 15

脚本

 #EXTRACT THE CONTENTS FROM THE TABLEAU SERVICES
    $content = Get-Content 'C:\Tableau Services\TableauServices.txt'
    $content.replace("`t", "").Replace(" is ",",").replace(".","").Replace("'","").Trim() | select -Skip 2 | Out-File 'C:\Tableau Services\TableauServices.csv'
    
    $iRunningNumber=1
    #Extract Services which have Stopped
    Write-Host ("The List of Services that have stopped are as below: - ")
    Import-CSV -Path 'C:\Tableau Services\TableauServices.csv' `
                -delimiter ”,” `
                -Header ServiceName, Status | 
                    Where-Object {$_.ServiceName -notlike "*Test Service 5*" -AND $_.ServiceName - notlike "*SAML Service 6*" -AND $_.ServiceName -notlike "*Database Service 7*" -AND $_.ServiceName -notlike "*Tableau Service 8*"} | 
                     Select-Object ServiceName, Status |
                        Where-Object {$_.Status -match "Stopped*"} | 
                            ForEach-Object {"$($iRunningNumber).) $($_.ServiceName)"; $iRunningNumber++}
                    

目前,要排除的服务在代码中是硬编码的。我想从配置文件中提取这些条件,然后从最终列表中搜索并排除。

我有另一个文件,其中包含要忽略的服务列表,如下所示:- 搜索文件.txt

Test Service 5
SAML Service 6
Database Service 7
Tableau Service 8

我已经尝试了我所知道的一切,但仍然没有解决方案。请求您的帮助

【问题讨论】:

  • 您的代码正在创建您正在阅读的 CSV 文件。该文件的内容在哪里?

标签: powershell csv powershell-3.0


【解决方案1】:

一些事情。

  1. 您无需创建 csv 文件即可立即将其导入回来。您可以使用ConvertFrom-Csv直接将csv数据转换为对象

  2. -Raw 参数在使用 Get-Content 时提供比未指定时更好的性能。但是,它会将您的文件作为单个字符串加载。出于这个原因,我将它与TableauServices 一起使用,因为我们将其编辑为单个字符串并为$ExcludeServicesConfig 省略了它,因为我们需要将数据作为后续调用$ExcludeServicesConfig.Contains($Item.ServiceName) 的数组

  3. 我重构了您的代码以使用 Foreach 循环,而不是将所有内容都填充到管道中。如果您以后遇到问题,这会使调试变得更加容易。

最终,关键的修改是检查每个项目是否是排除列表的一部分并做出相应的反应。

这是代码。

.

#EXTRACT THE CONTENTS FROM THE TABLEAU SERVICES
$content = Get-Content 'C:\Tableau Services\TableauServices.txt' -Raw
$ExludeServicesConfig = Get-Content -Path 'SearchFile.txt' 

$obj = $content.replace("`t", "").Replace(" is ", ",").replace(".", "").Replace("'", "").Trim() | 
    ConvertFrom-Csv -Header 'ServiceName', 'Status'
    
$iRunningNumber = 1


#Extract Services which have Stopped
Write-Host ("The List of Services that have stopped are as below: - ")

Foreach ($item in $obj) {
    if ($ExludeServicesConfig.Contains($Item.serviceName)) { Continue }
    if ( $item.Status -eq "Stopped") {
        "$($iRunningNumber).) $($item.ServiceName)"
        $iRunningNumber += 1
    }
}

【讨论】:

    【解决方案2】:

    如果您使用的是纯文本文件并且它们包含您发布的内容,您可以执行以下操作:

    $Ignore = (Get-Content SearchFile.txt | Foreach-Object {
        [regex]::Escape($_)}) -join '|'
    (Get-Content TableauServices.txt) -notmatch $Ignore -match 'Stopped' -replace "^.*?'([^']+)'.*$",'$1'
    

    说明:

    由于-match-notmatch 使用正则表达式匹配,您需要创建一个正则表达式友好的字符串。正则表达式中的 OR 等效项是 |。对于您想忽略的项目,我们可以使用| 加入它们。 [regex]::Escape() 的重点是转义搜索字符串中的任何特殊正则表达式字符。转义告诉正则表达式按字面意思匹配。

    ^ 匹配字符串的开头。 .*? 尽可能少的字符,直到匹配下一个字符(在我们的例子中为')。 '' 的字面匹配。 [^'] 是一个否定 (^) 字符类 ([]),用于匹配任何不是 ' 的字符。 + 匹配一个或多个前一个字符。 .* 贪婪地匹配零个或多个字符。 $ 是字符串的结尾。

    因为-replace 有两个部分,第一个匹配字符串,第二个充当替换。由于我们使用() 对匹配进行分组,因此它成为一个捕获组(组1,因为它是() 的第一组)。您可以使用语法'$CaptureGroup' 在替换字符串中引用捕获组,在这种情况下为'$1'

    【讨论】:

    • 似乎不起作用... 错误消息获取内容:找不到与参数名称“不匹配”匹配的参数。在 line:3 char:76 + ... TableauServices.txt" -notmatch $Ignore ... + ~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [Get-Content], ParameterBindingException + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetContentCommand
    • 您只需要在 Get-Content 命令周围加上括号。我将其添加到此代码中。
    猜你喜欢
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多