【问题标题】:Parsing a text file in PowerShell在 PowerShell 中解析文本文件
【发布时间】:2015-07-12 00:59:46
【问题描述】:

我有一个包含多个用户的文本文件(格式完全相同):

用户名:t-汉考克

电话号码:555555555

用户名:a-smith

电话号码:987654321

用户名:r-Byer

电话号码:123456789

我试图让所有这些用户进入一个具有两个属性(姓名和电话号码)的对象。 我尝试了Get-Content,尝试了其他帖子中的一些正则表达式,但我无法修改它们,因为我不明白。

这是怎么做到的?

【问题讨论】:

  • 你能展示你尝试过的东西吗?如果你这样做,通常会得到更好的回应
  • 文件中的文字真的每行文字之间有空行吗?
  • 为什么是三种不同的拼写方式,"phoneNumber"、"PhoneNumber" 和 "phonenumber"?

标签: regex parsing powershell powershell-3.0


【解决方案1】:

您在这里想要什么并不完全清楚 - 什么样的对象以及用于什么目的?

我会举一个你可以做什么的例子......

假设您想将该文本文件转换为 CSV 文件以便轻松导入 Excel,请从读取文件内容开始:

$input = Get-Content C:\TextFile.txt

现在,创建一个数组,您将在其中存储您创建的每个对象:

$array = @()

现在,我们将进入一个循环,解析文件内容。如果该行以“用户名”开头,则使用冒号作为分隔符分割该行,将第二项(0-relative 因此第二项为第一)抓取到一个变量中。

如果行以“PhoneNumber”开头,则将 $writeobj 变量设置为 true(在循环的每次迭代开始时重置为 false)并再次使用 split 将“PhoneNumber”值存储在 $PhoneNumber 中。

然后检查$writeobj 是否为真,如果是,则创建一个新对象,添加一个NoteProperty,其名称为用户名,用户名值存储在文件的前一行中。

然后添加一个名为 PhoneNumber 且值为 $PhoneNumber 的 NoteProperty。然后,将对象添加到数组中。

这会在文件内容中一直重复:

$input | foreach-object {
    $writeobj = $false
    $obj = New-Object System.Object
    If ($_ -match 'username*') {
        $Username = ($_ -split ':')[1]
    }
    If ($_ -match 'PhoneNumber*') {
        $PhoneNumber = ($_ -split ':')[1]
        $writeobj = $true
    }
    If ($writeobj){
        $obj | Add-Member -type NoteProperty -name Username -value $Username
        $obj | Add-Member -type NoteProperty -name PhoneNumber -value $PhoneNumber
        $array += $obj
    }
}

退出循环后,将数组导出为 CSV 文件:

$array | Export-Csv -path C:\test.csv -NoTypeInformation

所以,完整的脚本是:

$input = Get-Content C:\TextFile.txt
$array = @()
$input | foreach-object {
    $writeobj = $false
    $obj = New-Object System.Object
    If ($_ -match 'username*') {
        $Username = ($_ -split ':')[1]
    }
    If ($_ -match 'PhoneNumber*') {
        $PhoneNumber = ($_ -split ':')[1]
        $writeobj = $true
    }
    If ($writeobj){
        $obj | Add-Member -type NoteProperty -name Username -value $Username
        $obj | Add-Member -type NoteProperty -name PhoneNumber -value $PhoneNumber
        $array += $obj
    }
}
$array | Export-Csv -path C:\test.csv -NoTypeInformation

查看下面在 Excel 中打开的 CSV 文件的屏幕截图。

【讨论】:

  • 修改了我的解决方案以使用 -match 而不是 .Startswith,因为它没有给出好的结果,在最终的 CSV 文件中只显示中间用户 a-smith。还修改了循环逻辑以使其更加健壮,并在 excel 中添加了脚本创建的 CSV 的屏幕截图。
  • 示例输入文件有 3 种不同的拼写,"phoneNumber"、"PhoneNumber" 和 "phonenumber" .也许应该在这个答案中说一些关于区分大小写的内容(例如 “-match 运算符默认情况下不区分大小写” 或其他内容(我没有检查是否确实如此(不双关语)或不))?
  • @PeterMortensen 提供的解决方案不区分大小写,正如生成的 CSV 文件的屏幕抓取所示 - 使用相同的输入数据,输出在 csv 中有三个记录,就像在输入日。 Powershell 默认情况下基本上不区分大小写,匹配运算符也不例外。如果您希望它区分大小写,请改用 -cmatch 运算符,它明确区分大小写。
【解决方案2】:

我建议您改为将格式更改为 CSV,这样就很简单了。只需使用Import-Csv。

现在你可以做一些很长的行,它假定有效的文本文件,没有空行:

$content = Get-Content "C:\Users\You\Documents\test.txt"
$readUsername = $true
$data = @()
foreach ($line in $content)
{
    if($readUsername -eq $true) {
      $username = .. # Match the line against regex.
      $readUsername = $false
    } else {
       $phone = .. # Match the line against regex
       $readUsername = $true

       # We have grabbed username & phone
       $props = @{Name: $username, Phone: $phone}
       $obj = New-Object PSObject –Property $props
       $data += $obj
    }
}

# You now have access to $data.

【讨论】:

    【解决方案3】:

    我会使用regexes 来获取数据(下面的示例),您可能需要调整正则表达式来提取名称和数字,因为我只有您的小样本可以继续,并且我已经做了一些假设就像名称和数字中没有空格一样。

    ((Get-Content file.txt -Raw) -split '\n(?=username)') | % {
        $x = $_ -split '\r'
        New-Object PSOBJECT -Property @{
            name  = [regex]::Match($x[0],'(?<=username:\s*)\b.*\b')
            phone = [regex]::Match($x[1],'(?<=[Pp]hone[Nn]umber:\s*)\b.*\b')
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      • 2021-06-22
      • 1970-01-01
      • 2015-02-14
      • 1970-01-01
      • 2018-10-10
      • 2020-10-22
      相关资源
      最近更新 更多