您知道如何使用powershell将列DocumentNo移动到最后一列吗?
| D|Ref.Doc. |Row|DocumentNo |CoCd|Pstng Date
| W|5007534739| 1|65713191 |STCD|01/17/2016
| W|5007534739| 1|65713191 |STCD|01/17/2016
| W|5007534739| 1|65713191 |STCD|01/17/2016
预期输出
| D|Ref.Doc. |Row|CoCd|Pstng Date|DocumentNo
| W|5007534739| 1|STCD|01/17/2016|65713191
| W|5007534739| 1|STCD|01/17/2016|65713191
| W|5007534739| 1|STCD|01/17/2016|65713191
这是我尝试过的命令
(get-content $file -ReadCount 0) |
foreach {
'{0}|{1}|{2}|{3}|{5}|{6}|{4}' -f $_.split('|')
} | Set-Content $file2
代码工作正常,但万一DocumentNo将管道作为数据包含,如何处理?
答案 0 :(得分:2)
您可以执行以下操作:
$delimiter = "|"
$data = Get-Content "c:\tmp\test.csv";
$newCsv= ($data|Foreach-object { ($_ -split $delimiter)[@(0..3;5;6;4)] -join $delimiter})
# Set the new-ordered column content to the new-file
$newCsv|Set-Content C:\tmp\test2.csv
如果您想将所有这些都放在一行中,您可以执行以下操作:
Get-Content "c:\tmp\test.csv"|Foreach-object { ($_ -split '|')[@(0..3;5;6;4)] -join '|'}|Set-Content C:\tmp\test2.csv
请注意,如果您将get-content作为管道的一部分,则不能使用set-content,因为该文件将是打开的,并且不能将其作为流的一部分替换它的内容。
您必须使用第一种方法(首先阅读内容,然后将其传递给流)或将内容设置为不同的文件。
答案 1 :(得分:2)
如果在数据本身内部使用分隔符,它会破坏csv。我看到数据是固定宽度的(尽管长度和索引可能会因文件而异),所以我会采用不同的方法。
[Regex]::Match()
因为它返回匹配(列)的index
(起始位置)和length
(字符数)。$()
来插入步骤2中的index
和length
,因为它们对于每个文件可能都不相同。-replace
与生成的正则表达式一起使用来修改每一行的文本(因为$text
是一个数组)。 -replace
找到这些组,并使用$1$3$2
我可以说我希望在结果中插入哪些组。 (https://regex101.com/r/vE6vO9/1)解决方案:
#Sample text
$text = Get-Content .\Test.txt
#Analyze header (find DocumentNo placement in fixed-width file) and create regex
$regex = [regex]::Match($text[0], '\|DocumentNo\s+') | ForEach-Object { "^(.{$($_.Index)})(.{$($_.Length)})(.*)$" }
#Modify text
$text -replace $regex, '$1$3$2' | Set-Content .\TestOut.txt
TestOut.txt
| D|Ref.Doc. |Row|CoCd|Pstng Date|DocumentNo
| W|5007534739| 1|STCD|01/17/2016|65713191
| W|5007534739| 1|STCD|01/17/2016|65713191
| W|5007534739| 1|STCD|01/17/2016|65713191
您可能希望修剪尾随空格。请使用Trim()
:
$text -replace $regex, '$1$3$2' | ForEach-Object { $_.Trim() } | Set-Content .\TestOut.txt