在Powershell中将管道分隔文件更改为逗号分隔文件

在Powershell中将管道分隔文件更改为逗号分隔文件,powershell,Powershell,我有一个管道分隔的.TXT文件。我需要将分隔符改为逗号,但仍将文件扩展名保留为.TXT。该文件如下所示: 第1栏|第2栏 13 | 2019-09-30 96 | 2019-09-26 173 | 2019-09-25 我的脚本使用的是Windows Powershell 5.1版本 我正在使用以下代码: $file = New-Object System.IO.StreamReader -Arg "c:\file.txt" $outstream = [System.IO.StreamWrite

我有一个管道分隔的.TXT文件。我需要将分隔符改为逗号,但仍将文件扩展名保留为.TXT。该文件如下所示:

第1栏|第2栏

13 | 2019-09-30

96 | 2019-09-26

173 | 2019-09-25

我的脚本使用的是Windows Powershell 5.1版本

我正在使用以下代码:

$file = New-Object System.IO.StreamReader -Arg "c:\file.txt"
$outstream = [System.IO.StreamWriter] "c:\out.txt"
while ($line = $file.ReadLine()) {
$s = $line -replace '|', ','
$outstream.WriteLine($s)
}
$file.close()
$outstream.close()
输出文件不是用逗号替换管道,而是如下所示:

C、 o,l,u,m,n,1,|,C,o,l,u,m,n,2

1,3,2,0,1,9,0,9,3,0

9,6,2,0,1,9,0,9,2,6

1,7,3,|,2,0,1,9,-,0,9,-,2,5

您会发现and运算符很有意思

Get-Content -Path "C:\File.TXT" | ForEach-Object { ($_ -split "\|") -join "," } | Set-Content -Path "C:\Out.TXT"

您可以通过指定
-分隔符来使用
导入Csv
导出Csv

Import-Csv -Delimiter '|' -Path "c:\file.txt" | Export-Csv -Delimiter ',' -Path "c:\file.txt" -NoTypeInformation

答案的唯一问题在于如何替换输入中的
字符:

$s=$line-替换“|”、”和“#错误

PowerShell的
-replace
运算符需要一个正则表达式作为其第一个RHS操作数,
|
是一个正则表达式元字符(具有特殊含义)[1];若要将其用作文字字符,您必须对其进行转义

# '\'-escape regex metacharacter '|' to treat it literally.
$s = $line -replace '\|', ','
虽然非常灵活,在这种简单的情况下,您可以选择使用
[string]
类型的
.Replace()
方法,该方法执行文本字符串替换,因此不需要转义(它也比
-Replace
更快):



[1]
|
表示正则表达式中的一个替换,这意味着两边的子表达式都与输入字符串匹配,其中一个匹配就足够了;如果您的完整正则表达式正好是
|
,它将有效地匹配输入中每个字符前后的空字符串,这解释了您的症状;e、 例如,
'foo'-替换'|','@'
产生
@f@o@o@

投了反对票,因为@Jacob早些时候提供的答案更准确effective@StanislavCastek-如果您尝试Jacob编写的解决方案,则会出现问题-至少,在文件顶部会生成一个伪行。虽然从结构上看,querent发布的内容似乎符合bog标准CSV,但我从不认为发布的样本数据完全符合现实;如果文件中的其他行与两列CSV模型不匹配,
导入CSV
/
导出CSV
模型将失败,而我的模型不会失败。如果原始文件如示例所示与CSV完全一致,我承认Jacob的解决方案更快。@StanislavCastek-如果querent明确说明原始文件是CSV(无论文件名如何),我会提出Jacob的解决方案并进行必要的更正。这样(+1):即使您使用了
-NoTypeInformation
开关,也存在另一个潜在的复杂性(如果输入文件格式正确,这也无关紧要,重要的是输出是否为有效的CSV文件):
导出CSV
将始终双引号引用所有字段值。这是一个很好的解释,在我的回答中也适用于
-split
。谢谢,@JeffZeitlin;是的,您的
-split
/
-join
组合肯定也能工作,关于
-replace
.replace()
的要点与
-split
.split()
类似。谢谢!逃跑是有道理的,而且效果很好。我也试过了。Replace(),比-Replace替换为escape快了几秒钟。我很高兴听到这个消息,@Arijita。请允许我在下一条评论中给你一些新来者的标准建议:如果一个答案解决了你的问题,请点击大复选标记接受它(✓) 在它旁边,也可以选择向上投票(向上投票需要至少15个信誉点)。如果您发现其他答案有帮助,请向上投票。接受(为此您将获得2个信誉点)和向上投票有助于未来的读者。有关更多信息,请参阅。如果您的问题尚未完全回答,请提供反馈或。
导出CSV
将在文件顶部生成一个伪行,除非您包括
-NoTypeInformation
开关。但也请参阅我对@StanislavCastek的评论和我的答案。谢谢!(我一直在避免这样做,因为这是一个巨大的文件,需要一段时间才能完成。)“JeffZeitlin,你是正确的,我总是忘记包括<代码> -NoType信息< /代码>。我已经把答案包括进去了。@阿里吉塔,这是一个公平的观察,AFIK<代码>导入CSV 将它解析为内存中的一个对象,在<代码>导出CSV < /代码>将它转换回CSV。因此,考虑这是一个简单的方法,但是这不是最有效的方法。
# Use literal string replacement.
# Note: .Replace() is case-*sensitive*, unlike -replace
$s = $line.Replace('|', ',')