Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex Powershell从文本文件提取数据并转换为csv_Regex_String_Powershell_Substring - Fatal编程技术网

Regex Powershell从文本文件提取数据并转换为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

所以我有一个文本文件,如下所示

如何使用PowerShell获取mac地址和端口号(最右边的列),并将其输出到带有标题(mac,端口)的csv文件

我已经试过多次在文本文件中循环使用-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
从这里开始,我不知道如何将其转换为带有标题(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