【问题标题】:PowerShell Read file line by line, regex each line and store the item in an arrayPowerShell逐行读取文件,正则表达式每行并将项目存储在数组中
【发布时间】:2021-01-08 02:50:25
【问题描述】:

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

我的文件每一行都是这样的,有几千行……

Car   1FMZU77E22UC18440     Honda Civic
Car   SCBCR63W55C024793     GM Colorado 

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

我在 VIN 列的正则表达式之间的外观是 (?

我在这里尝试了解决方案,但不确定如何将其存储到数组中 - Read file line by line in PowerShell

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

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

编辑:第三列之后没有空格。我的 data2 数组的正则表达式将在后面 (?

【问题讨论】:

  • 好的,其余部分之间有多少空格?你真的没有给我们太多的东西。
  • 你的意思是在第三列之后?第三列之后没有空格。对于每一行,1111(总是固定长度)和 xxxx(固定长度数据)之间有 3 个空格; xxxx 和 yyyy 之间有 5 个空格(yyyy 不是定长数据)。我希望这一切都清楚了。
  • 那么 2222 和 zzzzz 和 wwwww 是没有分隔符的可变长度?
  • 请添加一个真实的数据样本并以代码格式包装它,以便可以轻松读取和复制以进行测试。

标签: arrays regex powershell


【解决方案1】:

如果没有一些真实(模拟)数据,我认为最好不要使用正则表达式。此外,这可以通过将其视为 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 $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

【讨论】:

    猜你喜欢
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多