在 PowerShell 中解析文本文件
Parsing a text file in PowerShell
我有一个包含多个用户的文本文件(格式完全相同):
username:t-Hancock
phoneNumber: 555555555
username:a-smith
PhoneNumber: 987654321
username:r-Byer
phonenumber: 123456789
我试图让所有这些用户进入一个具有两个属性(名称和 phone 号码)的对象。
我尝试了 Get-Content,尝试了其他帖子中的一些正则表达式,但我无法修改它们,因为我不明白。
这是怎么做到的?
我建议您将格式更改为 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.
我会使用 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')
}
}
你在这里想要什么还不是很清楚 - 什么样的对象和目的是什么?
我将举例说明您可以做什么...
假设您想将该文本文件转换为 CSV 文件以便于导入 Excel,请从读取文件内容开始:
$input = Get-Content C:\TextFile.txt
现在,创建一个数组,您将在其中存储您创建的每个对象:
$array = @()
现在,我们将进入一个循环,解析文件内容。如果该行以 "username" 开头,使用冒号作为分隔符拆分该行,将第二项(相对于 0,因此第二项是第一项)抓取到一个变量中。
如果该行以 "PhoneNumber" 开头,则将 $writeobj
变量设置为 true(在每次循环迭代开始时重置为 false)并将 "PhoneNumber" 值存储在$PhoneNumber
再次使用拆分。
然后检查 $writeobj
是否为真,如果是,则创建一个新对象,添加一个名为 Username 的 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 文件的屏幕截图。
我有一个包含多个用户的文本文件(格式完全相同):
username:t-Hancock
phoneNumber: 555555555
username:a-smith
PhoneNumber: 987654321
username:r-Byer
phonenumber: 123456789
我试图让所有这些用户进入一个具有两个属性(名称和 phone 号码)的对象。 我尝试了 Get-Content,尝试了其他帖子中的一些正则表达式,但我无法修改它们,因为我不明白。
这是怎么做到的?
我建议您将格式更改为 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.
我会使用 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')
}
}
你在这里想要什么还不是很清楚 - 什么样的对象和目的是什么?
我将举例说明您可以做什么...
假设您想将该文本文件转换为 CSV 文件以便于导入 Excel,请从读取文件内容开始:
$input = Get-Content C:\TextFile.txt
现在,创建一个数组,您将在其中存储您创建的每个对象:
$array = @()
现在,我们将进入一个循环,解析文件内容。如果该行以 "username" 开头,使用冒号作为分隔符拆分该行,将第二项(相对于 0,因此第二项是第一项)抓取到一个变量中。
如果该行以 "PhoneNumber" 开头,则将 $writeobj
变量设置为 true(在每次循环迭代开始时重置为 false)并将 "PhoneNumber" 值存储在$PhoneNumber
再次使用拆分。
然后检查 $writeobj
是否为真,如果是,则创建一个新对象,添加一个名为 Username 的 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 文件的屏幕截图。