PowerShell将无序文本转换为CSV

huangapple go评论52阅读模式
英文:

Powershell convert unordered Text to CSV

问题

Sure, here's the translated content:

我有一个系统,可以导出一个文本文件 [.txt],希望将文本转换为 .csv 文件。导出文件包含500多行,因此在Excel中手动处理非常慢。我无法更改导出格式的方式,因此无法使用分隔符。 😓

以下是导出的示例...

 ACC004 门禁控制 29/03/23 9000053641 801MS-0070 滑动 -1 -£391.00  -£255.31

 ACC061 门禁自动化 22/03/2023 9000053431 ZL92Z 控制 -1 -£139.50 -83.80

 ACC061 门禁自动化 27/03/2023 9000053538 STYLO-ME 摆动 -1 -£191.62 -£113.45

 ACT015 活动概念 31/03/2023 9000053739 801MP-0070 摆动 -2 -£324.76 -£238.69

 ADI005 ADI Gardner Ltd 29/03/2023 9000053642 806SS-0020 安全 -1 -£46.35 -£28.19

 ADI008 ADI Gardner Ltd 31/03/2023 9000053736 AX3024 摆动 -1 -£213.00 -£126.55

 ADI011 ADI Gardner Ltd 29/03/2023 9000053591 3199ZM3E 控制 -1 -£112.25 -£64.80

 AGD001 AGD Systems Ltd 23/03/2023 9000053465 AX3024 摆动 -1 -£200.65 -£123.79

我的计划是使用PowerShell遍历 .txt 文件的每一行,使用 foreach 循环将行转换为可以写入 CSV 文件的数组。我的难点是如何拆分行,以便将正确的值添加到正确的数组位置...

虽然我可以使用:-

 .Substring(0, 6)

来提取字符串开头的 ID [0],但下一个值 [1] 应包含帐户名称,其长度可以是任意字符长度和任意数量的空格。

示例 CSV

ID 名称 日期 订单 部件 类别 数量 价值 调整
ACC004 门禁控制 29/03/23 9000053641 801MS-0070 滑动 -1 -£391.00 -£255.31
ACC061 门禁自动化 22/03/2023 9000053431 ZL92Z 控制 -1 -£139.50 -83.80
ACC061 门禁自动化 27/03/2023 9000053538 STYLO-ME 摆动 -1 -£191.62 -£113.45

欢迎提供建议,让乐趣开始吧...

英文:

I have a system that exports a text file [.txt] and wish to convert the text to a .csv file. The export contains 500+ lines so manual manipulation in Excel is very slow. I have no means of changing the way the export is formatted so a delimiter is not possible. 😒

Below is an example of the export...

 ACC004 Access Control 29/03/23 9000053641 801MS-0070 Sliding -1 -£391.00  -£255.31

 ACC061 Access Automation 22/03/2023 9000053431 ZL92Z Control -1 -£139.50 -83.80

 ACC061 Access Automation 27/03/2023 9000053538 STYLO-ME Swing -1 -£191.62 -£113.45

 ACT015 Active Concept 31/03/2023 9000053739 801MP-0070 Swing -2 -£324.76 -£238.69

 ADI005 ADI Gardner Ltd 29/03/2023 9000053642 806SS-0020 Safety -1 -£46.35 -£28.19

 ADI008 ADI Gardner Ltd 31/03/2023 9000053736 AX3024 Swing -1 -£213.00 -£126.55

 ADI011 ADI Gardner Ltd 29/03/2023 9000053591 3199ZM3E Control -1 -£112.25 -£64.80

 AGD001 AGD Systems Ltd 23/03/2023 9000053465 AX3024 Swing -1 -£200.65 -£123.79

My plan is to use PowerShell to iterate through each line of the .txt file with a foreach loop and convert the line into an array that can be written to a CSV file. My stumbling block is how to split the row so that the correct values are added to the correct array positions...

Whilst I can use:-

 .Substring(0, 6)

To pull the ID [0] from the start of the string the next value [1] should contain the account name which can be any character length and any number of spaces.

Example CSV

ID Name Date Order Part Cat Qty Val Adj
ACC004 Access Control 29/03/23 9000053641 801MS-0070 Sliding -1 -£391.00 -£255.31
ACC061 Access Automation 22/03/2023 9000053431 ZL92Z Control -1 -£139.50 -83.80
ACC061 Access Automation 27/03/2023 9000053538 STYLO-ME Swing -1 -£191.62 -£113.45

Any suggestions would be gladly received, So the fun begins...

答案1

得分: 2

以下是使用正则表达式的代码示例:

$text = @"
ACC004 Access Control 29/03/23 9000053641 801MS-0070 Sliding -1 -£391.00  -£255.31
ACC061 Access Automation 22/03/2023 9000053431 ZL92Z Control -1 -£139.50 -83.80
ACC061 Access Automation 27/03/2023 9000053538 STYLO-ME Swing -1 -£191.62 -£113.45
ACT015 Active Concept 31/03/2023 9000053739 801MP-0070 Swing -2 -£324.76 -£238.69
ADI005 ADI Gardner Ltd 29/03/2023 9000053642 806SS-0020 Safety -1 -£46.35 -£28.19
ADI008 ADI Gardner Ltd 31/03/2023 9000053736 AX3024 Swing -1 -£213.00 -£126.55
ADI011 ADI Gardner Ltd 29/03/2023 9000053591 3199ZM3E Control -1 -£112.25 -£64.80
AGD001 AGD Systems Ltd 23/03/2023 9000053465 AX3024 Swing -1 -£200.65 -£123.79
"@
$pattern = "^(?<id>[^\s]+)\s+(?<name>.*) (?<date>\d{2}/\d{2}/\d+)\s+(?<order>\d+)\s+(?<part>[^\s]+)\s+(?<cat>.*)\s+(?<qty>.\d+)\s+(?<val>[^\s]+)\s+(?<adj>.*)&quot;"
$reader = [System.IO.StringReader]::new($text)
$table = [System.Collections.ArrayList]::new()

while(($line = $reader.ReadLine()) -ne $null)
{
   $line -match $pattern | Out-Null
   $id = $Matches.id.Trim()
   $name = $Matches.name.Trim()
   $date = $Matches.date.Trim()
   $order = $Matches.order.Trim()
   $part = $Matches.part.Trim()
   $cat = $Matches.cat.Trim()
   $qty = $Matches.qty.Trim()
   $val = $Matches.val.Trim()
   $adj = $Matches.adj.Trim()
   
   $newRow = [PSCustomObject]@{
      ID = $id
      Name = $name
      Date = $date
      Order = $order
      Part = $part
      Cat = $cat
      Qty = $qty
      Val = $val
      Adj = $adj
   }

   $table.Add($newRow) | Out-Null
   
}
$table | format-list
$table | export-csv 'c:\temp\test.csv'

希望这有帮助!

英文:

Try following code which uses Regex

<!-- begin snippet: js hide: false console: true babel: false -->

$text = @&quot;
ACC004 Access Control 29/03/23 9000053641 801MS-0070 Sliding -1 -&#163;391.00  -&#163;255.31
ACC061 Access Automation 22/03/2023 9000053431 ZL92Z Control -1 -&#163;139.50 -83.80
ACC061 Access Automation 27/03/2023 9000053538 STYLO-ME Swing -1 -&#163;191.62 -&#163;113.45
ACT015 Active Concept 31/03/2023 9000053739 801MP-0070 Swing -2 -&#163;324.76 -&#163;238.69
ADI005 ADI Gardner Ltd 29/03/2023 9000053642 806SS-0020 Safety -1 -&#163;46.35 -&#163;28.19
ADI008 ADI Gardner Ltd 31/03/2023 9000053736 AX3024 Swing -1 -&#163;213.00 -&#163;126.55
ADI011 ADI Gardner Ltd 29/03/2023 9000053591 3199ZM3E Control -1 -&#163;112.25 -&#163;64.80
AGD001 AGD Systems Ltd 23/03/2023 9000053465 AX3024 Swing -1 -&#163;200.65 -&#163;123.79
&quot;@
$pattern = &quot;^(?&lt;id&gt;[^\s]+)\s+(?&lt;name&gt;.*)(?&lt;date&gt;\d{2}/\d{2}/\d+)\s+(?&lt;order&gt;\d+)\s+(?&lt;part&gt;[^\s]+)\s+(?&lt;cat&gt;.*)\s+(?&lt;qty&gt;.\d+)\s+(?&lt;val&gt;[^\s]+)\s+(?&lt;adj&gt;.*)&quot;
$reader = [System.IO.StringReader]::new($text)
$table = [System.Collections.ArrayList]::new()

while(($line = $reader.ReadLine()) -ne $null)
{
   $line -match $pattern | Out-Null
   $id = $Matches.id.Trim()
   $name = $Matches.name.Trim()
   $date = $Matches.date.Trim()
   $order = $Matches.order.Trim()
   $part = $Matches.part.Trim()
   $cat = $Matches.cat.Trim()
   $qty = $Matches.qty.Trim()
   $val = $Matches.val.Trim()
   $adj = $Matches.adj.Trim()
   
   $newRow = [PSCustomObject]@{
      ID = $id
      Name = $name
      Date = $date
      Order = $order
      Part = $part
      Cat = $cat
      Qty = $qty
      Val = $val
      Adj = $adj
   }

   $table.Add($newRow) | Out-Null
   
}
$table | format-list
$table | export-csv &#39;c:\temp\test.csv&#39;

<!-- end snippet -->

答案2

得分: 0

你可以使用split来分割数据,然后使用正则表达式来搜索日期。一旦找到日期,你就知道前面的部分是账户和ID。由于ID似乎是一个“Word”,你可以知道在ID和日期之间的“Words”是你的账户名称。

英文:

Looking at your data. You could use split to split them up, then use a regex expression to search for the date. Once you found the date you know the ones prior are the account and id. Since ID seems to be one "Word" you know the "Words" between ID and date are your account name.

huangapple
  • 本文由 发表于 2023年5月22日 04:23:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76301788.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定