regex - 是否可以将 Get-Content、ForEach-Object string -match 替换为 Select-String cmdlet?

标签 regex powershell

我有一个固定宽度的文件,其记录格式如下

DDEDM2018890                                                                 19960730015000010000
DDETPL015000                                                                 20150515015005010000
DDETPL015010                                                                 20150515015003010000
DDETPL015020                                                                 20150515015002010000
DDETPL015030                                                                 20150515015005010000
DDETPL015040                                                                 20150515015000010000

前 3 个字符标识记录类型,在上面的示例中,所有记录都是 DDE 类型,但文件中也有不同类型的行。

以下带有命名捕获组的正则表达式会根据我的目的解析每个记录中的相关信息(请注意,它还会过滤到 DDE 记录类型:

DDE(?<Database>\w{3})\d{2}(?<CategoryCode>\d{2})(?<CategoryId>\d{1})\d\s+\d{8}\d{3}(?<Length>\d{3})

this excellent online parser上使用这个正则表达式

我编写了一个脚本,使用 Get-ContentForEach-ObjectSelect-Object cmdlet 来转换固定宽度文件到 csv 文件中。

我想知道是否可以用单个 Select-String cmdlet 替换 Get-ContentForEach-Object cmdlet?

#this powershell script reads fixed width file and generates a csv file of the relevant & converted values

#Prepare HashSet object for Select-Object to convert CategoryCode and append with CategoryId
$Category = @{
    Name = "Category"
    Expression = {
        $cat = switch($_.CategoryCode) 
        {
            "50"{"A"}
            "54"{"C"}
            "60"{"F"}
            "66"{"I"}
            "74"{"M"}
            "88"{"T"}
        } 
        $cat+$_.CategoryId
    }
}

gc "C:\Path\To\File.txt" | % { 
        if($_ -match "DDE(?<Database>\w{3})\d{2}(?<CategoryCode>\d{2})(?<CategoryId>\d{1})\d\s+\d{8}\d{3}(?<Length>\d{3}).*$")
        {
            #$matches is a hashset of named capture groups, convert to object to allow Select-Object to handle hashset elements as object properties
            [PSCustomObject]$matches
        }
    } | select Database, $Category, Length #| export-csv "AnalysisLengths.csv" -NoTypeInformation

在我完成脚本之前,我尝试使用Select-String cmdlet,但不知道如何使用它,我相信它可以以更 Eloquent 方式达到相同的结果。 ..这就是我所拥有的:

##Could this be completed with just the Select-String commandlet instead of Get-Content+ForEach+Select-Object?
Select-String -Path "C:\Path\To\File.txt" `
    -Pattern "DDE(?<Database>\w{3})\d{2}(?<CategoryCode>\d{2})(?<CategoryId>\d{1})\d\s+\d{8}\d{3}(?<Length>\d{3})" `
    | Select-Object -ExpandProperty Matches 

使用-ExpandProperty应将Microsoft.PowerShell.Commands.MatchInfo Matches属性转换为实际的System.Text.RegularExpressions .Match 每行对象...

另请参阅Powershell Select-Object vs ForEach on Select-String results

最佳答案

这是一种方法(我并不为此感到自豪)

Select-String -Path "C:\Path\To\File.txt" -Pattern "DDE(?<Database>\w{3})\d{2}(?<CategoryCode>\d{2})(?<CategoryId>\d{1})\d\s+\d{8}\d{3}(?<Length>\d{3})" | %{New-Object -TypeName PSObject -Property @{Database=$_.matches.groups[1];CategoryCode=$_.matches.groups[2];CategoryId=$_.matches.groups[3];Length=$_.matches.groups[4]}} | export-csv "C:\Path\To\File.csv"

关于regex - 是否可以将 Get-Content、ForEach-Object string -match 替换为 Select-String cmdlet?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30419612/

相关文章:

c# - 为什么这个正则表达式匹配?

python - 如何使用 python 正则表达式在相同模式之间获取行

powershell - 在 Powershell 中使用 Get-EventLog 远程读取事件日志

arrays - PowerShell-在forEach循环中未创建锯齿状数组

通过测试连接进行Powershell尝试/捕获

svn - 为什么这个 PowerShell 脚本删除 svn :mergeinfo from the root directory?

json - 使用模板、参数文件和 powershell 创建可用性 Web 测试 | New-AzApplicationInsightsWebTest

regex - 如何设置此正则表达式的最大长度?

c# - 正则表达式允许一组重复不同时间的字符

java - 正则表达式 - 接受拉丁/ucs2 字符