Regex Powershell从文本文件提取数据并转换为csv
所以我有一个文本文件,如下所示 如何使用PowerShell获取mac地址和端口号(最右边的列),并将其输出到带有标题(mac,端口)的csv文件 我已经试过多次在文本文件中循环使用-replace。我留下了我想要的数据,这很好。但它似乎过于复杂,我仍然面临着用标题输出到csv的问题Regex Powershell从文本文件提取数据并转换为csv,regex,string,powershell,substring,Regex,String,Powershell,Substring,所以我有一个文本文件,如下所示 如何使用PowerShell获取mac地址和端口号(最右边的列),并将其输出到带有标题(mac,端口)的csv文件 我已经试过多次在文本文件中循环使用-replace。我留下了我想要的数据,这很好。但它似乎过于复杂,我仍然面临着用标题输出到csv的问题 $file = Get-Content file.txt $file | ForEach-Object {$_ -replace ' ', '' -replace 'Dynamic', '' -replac
$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
从这里开始,我不知道如何将其转换为带有标题(mac、端口)的csv
就像我说的。必须有一种更有效的方法来过滤掉这些数据
非常感谢您的帮助。在评论中说堆栈溢出不是代码编写服务,我还是要写一些代码 下面的代码假定存储文本的文件名在变量
$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”)。但关键是,您要创建一个具有成员属性
MAC
和Port
的PSObject
,为这些属性分配必要的值,然后将这些对象发送到CSV。您可以使用regex筛选出所需的部分(MAC和Port),如下所示:
$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
正则表达式详细信息:
^ 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)
^在行首(字符串开头或换行符后)断言位置
. 匹配不是换行符的任何单个字符
+? 在一次和无限次之间,尽可能少的次数,根据需要扩展(惰性)
(?匹配下面的正则表达式,并将其匹配捕获到名为“mac”的backreference中
[0-9A-F]匹配下表中的单个字符
介于“0”和“9”之间的字符
介于“A”和“F”之间的字符
{4} 正好4次
\.按字面意思匹配字符“.”
[0-9A-F]匹配下表中的单个字符
介于“0”和“9”之间的字符
介于“A”和“F”之间的字符
{4} 正好4次
\.按字面意思匹配字符“.”
[0-9A-F]匹配下表中的单个字符
介于“0”和“9”之间的字符
介于“A”和“F”之间的字符
{4} 正好4次
)
. 匹配不是换行符的任何单个字符
+? 在一次和无限次之间,尽可能少的次数,根据需要扩展(惰性)
(?匹配下面的正则表达式,并将其匹配捕获到名为“port”的backreference中
\d匹配单个数字0..9
+在一次和无限次之间,尽可能多次,根据需要回馈(贪婪)
)
$Assert在行尾的位置(在字符串末尾或换行符之前)
如果您正在寻找通用解决方案(自动定义列),您可能希望尝试此方法,另请参见:。我刚刚添加了一个新功能,您可以提供列(属性)名称列表,而不是对齐的标题行:
$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
你尝试过什么,你尝试过的又是如何失败的?理想情况下,您应该提供您尝试过的内容的详细信息,并包括关于失败原因的具体信息,以及错误消息和/或错误输出。不是代码编写服务;最好的问题是那些提供有用信息的问题,这样那些回答问题的人可以引导你设计出自己的正确答案。看一个好问题。
^ 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)
$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