所以我有一个如下所示的文本文件。
我怎么能使用PowerShell来获取mac地址和端口号(最右边一列)并将其输出到带有标头(mac,端口)的csv文件中?
1 010D.0C93.A02C Dynamic Gi1/0/5
1 011B.782D.6719 Dynamic Gi1/0/22
1 0003.4790.B479 Dynamic Gi1/0/1
1 0054.B671.1EB8 Dynamic Gi1/0/2
我尝试仅遍历文本文件并多次使用-replace。我剩下了想要的数据,这很好。但它似乎过于复杂,我仍然面临着将输出与标头输出到csv的问题。
$file = Get-Content file.txt
$file | ForEach-Object {$_ -replace ' ', '' -replace 'Dynamic', ''
-replace 'Management', '' -replace 'Gi1/0/', ', '}
这是我尝试过的。它输出如下:
010D.0C93.A02C, 5
011B.782D.6719, 22
0003.4790.B479, 1
0054.B671.1EB8, 2
从这里,我不确定如何将其转换为带标头的csv(mac,端口) 就像我说的必须有一种更有效的方法来过滤掉这些数据。
感谢您的帮助。
答案 0 :(得分:1)
在评论中说Stack Overflow不是代码编写服务,我还是要编写一些代码...
以下代码假定存储文本的文件名位于变量$textfilename
中,并且所需CSV文件的名称位于变量$csvfilename
中。
Get-Content -Path $textfilename |
ForEach-Object {
New-Object -TypeName PSObject -Property @{
MAC=$_[9..22] -join ""
Port=$_[44..($_.length-1)] -join ""
}
} |
Export-CSV -Path $csvfilename -Append -NoTypeInformation
请注意,我通过坐在那里计数来找出子字符串的“字段位置”;无疑有更好的方法。我的代码给出的是端口名称,而不是数字(也就是说,我产生的是“ Gi1 / 0/22”而不是“ 22”)。但是,关键是要创建具有成员属性PSObject
和MAC
的{{1}},为这些属性分配必要的值,然后将这些对象发送到CSV。 / p>
答案 1 :(得分:1)
您可以使用正则表达式过滤出所需的部分(mac和端口),如下所示:
$result = Get-Content -Path 'X:\file.txt' | ForEach-Object {
if ($_ -match '^.+?(?<mac>[0-9A-F]{4}\.[0-9A-F]{4}\.[0-9A-F]{4}).+?(?<port>\d+)$') {
[PsCustomObject]@{
'mac' = $matches['mac']
'port' = $matches['port']
}
}
}
# output on screen
$result
# output to Csv file
$result | Export-Csv -Path 'X:\macports.csv' -NoTypeInformation
输出:
mac port --- ---- 010D.0C93.A02C 5 011B.782D.6719 22 0003.4790.B479 1 0054.B671.1EB8 2
正则表达式详细信息:
^ Assert position at the beginning of a line (at beginning of the string or after a line break character)
. Match any single character that is not a line break character
+? Between one and unlimited times, as few times as possible, expanding as needed (lazy)
(?<mac> Match the regular expression below and capture its match into backreference with name “mac”
[0-9A-F] Match a single character present in the list below
A character in the range between “0” and “9”
A character in the range between “A” and “F”
{4} Exactly 4 times
\. Match the character “.” literally
[0-9A-F] Match a single character present in the list below
A character in the range between “0” and “9”
A character in the range between “A” and “F”
{4} Exactly 4 times
\. Match the character “.” literally
[0-9A-F] Match a single character present in the list below
A character in the range between “0” and “9”
A character in the range between “A” and “F”
{4} Exactly 4 times
)
. Match any single character that is not a line break character
+? Between one and unlimited times, as few times as possible, expanding as needed (lazy)
(?<port> Match the regular expression below and capture its match into backreference with name “port”
\d Match a single digit 0..9
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)
$ Assert position at the end of a line (at the end of the string or before a line break character)
答案 2 :(得分:0)
如果您正在寻找通用解决方案(自动定义了列),则可能要尝试使用ConvertFrom-SourceTable
,另请参见:How can I save lines with spaces between characters in the right way (Array)?。
我刚刚添加了一个新功能,您可以在其中提供列(属性)名称的列表,而不是对齐的标题行:
$Table = '
1 010D.0C93.A02C Dynamic Gi1/0/5
1 011B.782D.6719 Dynamic Gi1/0/22
1 0003.4790.B479 Dynamic Gi1/0/1
1 0054.B671.1EB8 Dynamic Gi1/0/2'
ConvertFrom-SourceTable -Header Count,Address,Mode,Port $Table |
Select-Object -Property Address, @{n = 'Port'; e = {$_.Port.Split('/')[-1]}}
Address Port
------- ----
010D.0C93.A02C 5
011B.782D.6719 22
0003.4790.B479 1
0054.B671.1EB8 2