首页 > 解决方案 > PowerShell 逐行读取文件,正则表达式每行并将项目存储在数组中

问题描述

PowerShell的新手..我正在尝试逐行读取文件并将信息正则表达式转换为2个数组,以便以后可以使用这些数组进行更多处理。

我的文件的每一行看起来像这样,有数千行......

Car   1FMZU77E22UC18440     Honda Civic
Car   SCBCR63W55C024793     GM Colorado 

我需要将 VIN 号存储到 data1 数组中,并将汽车模型存储到 data2 数组中。car 栏和 VIN 号栏之间总是有 3 个空格;VIN 号栏和车型栏之间有 5 个空格。数据的长度不同,但空格用作分隔符。

我在 VIN 列的正则表达式之间的外观是 (?<=\s\s\s).*?(?=\s\s\s\s\s)

我在这里尝试了解决方案,但不确定如何将其存储到数组中 -在 PowerShell 中逐行读取文件

foreach($line in Get-Content myfile.txt) {
if($line -match $regex){
    $data1 += $line.matches.value
    }
}

我的 data1 数组是空的。我怎样才能做到这一点?谢谢。

编辑:第三列之后没有空格。我的 data2 数组的正则表达式将在后面 (?<=\s\s\s\s\s)。不确定它是否有效,因为我还不能存储我的数据。我知道我的正则表达式来自 c#...不确定它是否适用于 PowerShell。

标签: arraysregexpowershell

解决方案


如果没有一些真实(模拟)数据,我认为最好不要使用正则表达式。此外,这可以通过将其视为 CSV 来大大简化。

首先进行此测试,其他人也可以尝试,我们将制作一个示例文件

$tempfile = New-TemporaryFile

$data = @'
1111   xxxx     yyyyyyyyyyyyyyyy 2222 zzzz wwwwwww
3333   aaaa     bbbbbbbbbbbbbbbb 4444 cccc ddddddd
'@ | Set-Content $tempfile -Encoding utf8

接下来,我们在用逗号替换空格的同时阅读信息。如果您的数据有空格,那么这当然需要调整或不使用,具体取决于。

(Get-Content $tempfile) -replace '\s+',','

1111,xxxx,yyyyyyyyyyyyyyyy,2222,zzzz,wwwwwww
3333,aaaa,bbbbbbbbbbbbbbbb,4444,cccc,ddddddd

现在我们知道我们的数据是正确的,在指定标题的同时导入为 CSV。您可以提供有意义的标题,因为您知道信息是什么。

(Get-Content $tempfile) -replace '\s+',',' | ConvertFrom-Csv -Header a,b,c,d,e,f

a : 1111
b : xxxx
c : yyyyyyyyyyyyyyyy
d : 2222
e : zzzz
f : wwwwwww

a : 3333
b : aaaa
c : bbbbbbbbbbbbbbbb
d : 4444
e : cccc
f : ddddddd

如果您只想要某些列,只需选择那些。

(Get-Content $tempfile) -replace '\s+',',' | 
    ConvertFrom-Csv -Header a,b,c,d,e,f | Select b,c,e,f -OutVariale data

b    c                e    f      
-    -                -    -      
xxxx yyyyyyyyyyyyyyyy zzzz wwwwwww
aaaa bbbbbbbbbbbbbbbb cccc ddddddd

现在相应地分配它

$data | select b,e -OutVariable data1

b    e   
-    -   
xxxx zzzz
aaaa cccc

$data | select c,f -OutVariable data2

c                f      
-                -      
yyyyyyyyyyyyyyyy wwwwwww
bbbbbbbbbbbbbbbb ddddddd

编辑

你有意义的数据改变了我的建议。也很好奇额外的列在哪里,因为它不像你最初展示的那样。根据您显示的数据,我有三种不同的选择。

同样,从一些示例数据开始

$tempfile = New-TemporaryFile

@'
Car   1FMZU77E22UC18440     Honda CiviC
Car   SCBCR63W55C024793     GM Colorado
Truck   SZXYR63W55C165487     GM some model
'@ | Set-Content $tempfile -Encoding utf8

选项 1 - ConvertFrom-String

ConvertFrom-String 可以根据您作为“训练”数据提供的模板解析数据。

$template = @'
{Type*:abc}   {VIN:ABCDEFGH123456789}     {Model:some model}
{Type*:abcde}   {VIN:sample}     {Model:a some model}
'@

现在我们应用模板。使其逐行优于正则表达式的一方面是您可以使用-Raw非常快的获取内容的快速参数。

get-content $tempfile -Raw |
    ConvertFrom-String -TemplateContent $template -OutVariable data

Type  VIN               Model        
----  ---               -----        
Car   1FMZU77E22UC18440 Honda CiviC  
Car   SCBCR63W55C024793 GM Colorado  
Truck SZXYR63W55C165487 GM some model

如果您不需要该类型,请忽略它。将其设置为您的变量,例如

$data1,$data2 = $data.vin,$data.model

变量的内容$data1$data2

$data2
Honda CiviC
GM Colorado
GM some model

$data1
1FMZU77E22UC18440
SCBCR63W55C024793
SZXYR63W55C165487

选项 2 - 正则表达式 Get-Content / 逐行

Get-Content $tempfile | foreach {
    if($_ -match '(?<=[\s]{3})(\w*)[\s]{5}(.*)$')
    {
        [PSCustomObject]@{
            Model = $matches.2
            VIN   = $matches.1
        }
    }
}

再次根据需要设置变量

$data1,$data2 = $data.vin,$data.model

选项 3 - Select-String(可能更接近选项 1 的速度)

Select-String -path $tempfile -Pattern '(?<=[\s]{3})(\w*)[\s]{5}(.+)' -AllMatches | ForEach {
    $_.Matches | foreach {
        [PSCustomObject]@{
            Model = $_.groups[2].value
            VIN   = $_.groups[1].value
        }
    }
} -OutVariable data

推荐阅读