【问题标题】:Regex in PowerShell matches only first match of the linePowerShell 中的正则表达式仅匹配该行的第一个匹配项
【发布时间】:2017-11-17 20:35:11
【问题描述】:

我需要构建一个脚本,该脚本从各种日志文件中读取数据并使用 powershell 将数据放入 csv 中。输出 csv 应将第一列作为日志文件的名称,第二列应包含日志文件中的某些特定内容。第二列的内容不应在同一文件中出现两次,这就是第一列包含日志文件名。我已设法提取这两种数据类型,但我的脚本仅使用正则表达式模式匹配第一个匹配项,然后将结果放入 csv。

我正在使用以下脚本:

$test = gc .\datalog.txt | Select-String -Pattern '"\w:\\\w+\\' -NotMatch |
ForEach-Object {
New-Object psobject -Property @{
D_no = [regex]::Matches($_, '^[^\:]*[^\.log:]')
D_name = [regex]::Matches($_, '((?!\\)\w+\S+(?=\\)|(\w:\w+)[^"])').Groups[1].value
    }
}
$test | Select-Object D_no, D_name | Export-Csv abc.csv -NoTypeInformation

我脚本中的 D_name 仅匹配行中的第一个匹配项,因为我的预期操作是使用 D_name 中的正则表达式捕获所有条目。但是,当我使用

时,正则表达式工作正常
Select-String -allmatches '^[^\:]*[^\.log:]|(?!\\)\w+\S+(?=\\)|(\w:\w+)[^"]').Matches.Value

但是这给了我一个单独的列中 D_no 和 D_name 的数据。 The sample data can be found here

【问题讨论】:

    标签: regex powershell csv


    【解决方案1】:

    对于 D_name,您只提取了一个匹配组 - Groups[1].value。所以这是预期的结果。要将所有匹配结果放入D_name,然后将其正确导出为 CSV,您必须将它们组合成一个字符串。例如:

    New-Object psobject -Property @{
    D_no = [regex]::Matches($_, '^[^\:]*[^\.log:]').Value
    D_name = ([regex]::Matches($_, '((?!\\)\w+\S+(?=\\)|(\w:\w+)[^"])') | foreach {$_.Value}) -join ','
    } 
    

    请注意,从D_no 的第一个表达式中,您还会得到一个 MatchCollection,但仅包含 1 个元素。我建议从中获取一个 Value 属性。

    【讨论】:

    • 但是现在 D_name 中的值在一行中,而不是每个单元格中的单独值
    • 首先,在您的问题中,您说的是“第二列的内容”。这样对吗?其次,export-csv 不支持任意数量的列。它检查管道中的第一个对象,并仅包含所有其他对象的属性。您可以尝试通过将匹配项以逗号分隔的字符串导出到文件(实际上是 CSV 格式)来模拟 export-csv
    猜你喜欢
    • 2013-12-01
    • 1970-01-01
    • 2011-06-17
    • 2012-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    • 1970-01-01
    相关资源
    最近更新 更多