使用 Powershell 打印包含制表符的 txt 文件
Print a txt-file containing tab characters using Powershell
我正在尝试在 Powershell 中编写一个脚本来自动打印文本文件的内容。但是,打印时我的制表符被删除,导致最终输出难以阅读。
我提供了一个 MWE 来说明这个问题。
MWE.txt 的内容(以 ANSI 编码;→
表示制表符):
FOO→1,23→4,56
我的 powershell 脚本:
$fname = "C:\MWE.txt"
Get-Content $fname | Out-Printer -name "Microsoft XPS Document Writer"
为了避免浪费纸张,我一直在使用XPS writer,但最终还是要换成真正的打印机。真实纸张上的输出是相同的,我也排除了。
问题是在打印输出中,制表符被擦除,产生:
FOO1,234,56
但是,如果我改为将 Out-Printer
更改为 Out-String
,控制台会正确显示文件内容。我到底做错了什么?该文件在记事本和记事本++中都正确显示了标签,我也尝试过UTF-8编码。
编辑 2018-07-12 10:20
我要打印的文件的内容结构,它是由系统自动生成并放在我无法访问的网络服务器上的。为清楚起见,我使用 →
表示制表符,使用 ·
表示 space:
MWE·-·TestFile·:·
0)→Time
1)→Temperature·1
2)→Humidity
3)→Pressure·A-B
4)→Pressure·A-C
5)→Pressure·D-C
0)···················→1)→2)→3)→4)→5)→
2018-07-04 12:00:00→22,03→5,34→18,93→23,10→10,10
2018-07-04 13:00:00→21,99→5,22→18,75→23,56→10,00
2018-07-04 14:00:00→21,99→5,17→18,55→23,54→10,15
2018-07-04 15:00:00→22,03→5,25→18,73→23,41→8,33
您很接近,并且您自己偶然发现了一个解决方法 - 使用 Out-String
。您可以在将内容发送到打印机之前将 Out-String
添加到管道中:
Get-Content $fname | Out-String | Out-Printer -Name "Microsoft XPS Document Writer"
如果以上方法不适合您,您可以尝试自己处理制表符:
( Get-Content $fname -Raw ).Split( "`t" ) -Join "`t"
如果显示的输出符合您的预期,您可以将其通过管道传输到 Out-Printer
(Out-String
不是必需的,因为 -Join
连接成一个字符串):
( Get-Content $fname -Raw ).Split( "`t" ) -Join "`t" |
Out-Printer -Name "Microsoft XPS Document Writer"
但是,这似乎是 Out-Printer
的错误,因为评论和其他答案的成功率各不相同。已知上述变通办法至少适用于 Windows 10.0.15063.0
(我目前 运行 并测试过的版本),但在更高版本中可能已停止工作。
您可以尝试将制表符转换为空格作为解决方法:
# This is set to 5 spaces here, but can be any number of
# spaces you want to represent a tab character
$replaceTabString = " "
( Get-Content $fname -Raw ).Replace( "`t", $replaceTabString ) |
Out-Printer -Name "Microsoft XPS Document Writer"
我没有解释 - 症状听起来像 bug(也影响 Microsoft Print To PDF
打印机)并且它似乎特定于 tab 个字符,而 spaces 工作正常。
但是,我可以提供一个 解决方法 - 假设最终目标是创建 aligned 输出列,而事实并非如此需要专门使用 tabs 来实现:
Get-Content "C:\MWE.txt" | ForEach-Object {
# Construct a custom object whose properties contain the
# tab-separated tokens on the input line.
$obj = New-Object PSCustomObject; $i = 0
foreach ($val in $_ -split "`t") {
Add-Member -InputObject $obj -NotePropertyName ('col' + ++$i) -NotePropertyValue $val
}
$obj
} | Format-Table -Property (1..6 | % { 'col' + $_ }) -HideTableHeaders |
Out-Printer -Name "Microsoft XPS Document Writer"
ForEach-Object
脚本块将每个输入行按制表符拆分为标记,并构造一个自定义 object,其属性包含各个标记。
Format-Table
使用使用 空格 对齐的列创建 table 输出; -HideTableHeaders
抑制 table header 的输出,它通常会显示(自动生成的)属性 名称。
- 请注意,由于输入的行具有 不同的 列计数,
-FormatTable
必须明确指示要显示哪些列,这就是 (1..6 | % { 'col' + $_ })
做:它创建了一个包含所有 auto-generated 列名称的数组,基于 最多 6 列可以存在的假设,这对您的示例输入是正确的 - 调整根据需要那个数字。 (为了安全起见,您也可以指定一个更大的数字,例如 20
,但这会减慢处理速度。
将 Format-Table
的输出通过管道传输到 Out-Printer -Name "Microsoft XPS Document Writer"
似乎会产生具有对齐列的所需表格输出。
- 如果列值最终被 截断(表示为
...
),您需要调整 Format-Table
调用,例如使用自定义列宽- 参见我的 this answer。
运行 这针对您的示例输入在控制台中产生以下 6 列布局,输出 XPS 文档呈现类似:
MWE·-·TestFile·:·
0) Time
1) Temperature·1
2) Humidity
3) Pressure·A-B
4) Pressure·A-C
5) Pressure·D-C
0)··················· 1) 2) 3) 4) 5)
2018-07-04 12:00:00 22,03 5,34 18,93 23,10 10,10
2018-07-04 13:00:00 21,99 5,22 18,75 23,56 10,00
2018-07-04 14:00:00 21,99 5,17 18,55 23,54 10,15
2018-07-04 15:00:00 22,03 5,25 18,73 23,41 8,33
我正在尝试在 Powershell 中编写一个脚本来自动打印文本文件的内容。但是,打印时我的制表符被删除,导致最终输出难以阅读。
我提供了一个 MWE 来说明这个问题。
MWE.txt 的内容(以 ANSI 编码;→
表示制表符):
FOO→1,23→4,56
我的 powershell 脚本:
$fname = "C:\MWE.txt"
Get-Content $fname | Out-Printer -name "Microsoft XPS Document Writer"
为了避免浪费纸张,我一直在使用XPS writer,但最终还是要换成真正的打印机。真实纸张上的输出是相同的,我也排除了。
问题是在打印输出中,制表符被擦除,产生:
FOO1,234,56
但是,如果我改为将 Out-Printer
更改为 Out-String
,控制台会正确显示文件内容。我到底做错了什么?该文件在记事本和记事本++中都正确显示了标签,我也尝试过UTF-8编码。
编辑 2018-07-12 10:20
我要打印的文件的内容结构,它是由系统自动生成并放在我无法访问的网络服务器上的。为清楚起见,我使用 →
表示制表符,使用 ·
表示 space:
MWE·-·TestFile·:·
0)→Time
1)→Temperature·1
2)→Humidity
3)→Pressure·A-B
4)→Pressure·A-C
5)→Pressure·D-C
0)···················→1)→2)→3)→4)→5)→
2018-07-04 12:00:00→22,03→5,34→18,93→23,10→10,10
2018-07-04 13:00:00→21,99→5,22→18,75→23,56→10,00
2018-07-04 14:00:00→21,99→5,17→18,55→23,54→10,15
2018-07-04 15:00:00→22,03→5,25→18,73→23,41→8,33
您很接近,并且您自己偶然发现了一个解决方法 - 使用 Out-String
。您可以在将内容发送到打印机之前将 Out-String
添加到管道中:
Get-Content $fname | Out-String | Out-Printer -Name "Microsoft XPS Document Writer"
如果以上方法不适合您,您可以尝试自己处理制表符:
( Get-Content $fname -Raw ).Split( "`t" ) -Join "`t"
如果显示的输出符合您的预期,您可以将其通过管道传输到 Out-Printer
(Out-String
不是必需的,因为 -Join
连接成一个字符串):
( Get-Content $fname -Raw ).Split( "`t" ) -Join "`t" |
Out-Printer -Name "Microsoft XPS Document Writer"
但是,这似乎是 Out-Printer
的错误,因为评论和其他答案的成功率各不相同。已知上述变通办法至少适用于 Windows 10.0.15063.0
(我目前 运行 并测试过的版本),但在更高版本中可能已停止工作。
您可以尝试将制表符转换为空格作为解决方法:
# This is set to 5 spaces here, but can be any number of
# spaces you want to represent a tab character
$replaceTabString = " "
( Get-Content $fname -Raw ).Replace( "`t", $replaceTabString ) |
Out-Printer -Name "Microsoft XPS Document Writer"
我没有解释 - 症状听起来像 bug(也影响 Microsoft Print To PDF
打印机)并且它似乎特定于 tab 个字符,而 spaces 工作正常。
但是,我可以提供一个 解决方法 - 假设最终目标是创建 aligned 输出列,而事实并非如此需要专门使用 tabs 来实现:
Get-Content "C:\MWE.txt" | ForEach-Object {
# Construct a custom object whose properties contain the
# tab-separated tokens on the input line.
$obj = New-Object PSCustomObject; $i = 0
foreach ($val in $_ -split "`t") {
Add-Member -InputObject $obj -NotePropertyName ('col' + ++$i) -NotePropertyValue $val
}
$obj
} | Format-Table -Property (1..6 | % { 'col' + $_ }) -HideTableHeaders |
Out-Printer -Name "Microsoft XPS Document Writer"
ForEach-Object
脚本块将每个输入行按制表符拆分为标记,并构造一个自定义 object,其属性包含各个标记。Format-Table
使用使用 空格 对齐的列创建 table 输出;-HideTableHeaders
抑制 table header 的输出,它通常会显示(自动生成的)属性 名称。- 请注意,由于输入的行具有 不同的 列计数,
-FormatTable
必须明确指示要显示哪些列,这就是(1..6 | % { 'col' + $_ })
做:它创建了一个包含所有 auto-generated 列名称的数组,基于 最多 6 列可以存在的假设,这对您的示例输入是正确的 - 调整根据需要那个数字。 (为了安全起见,您也可以指定一个更大的数字,例如20
,但这会减慢处理速度。
- 请注意,由于输入的行具有 不同的 列计数,
将
Format-Table
的输出通过管道传输到Out-Printer -Name "Microsoft XPS Document Writer"
似乎会产生具有对齐列的所需表格输出。- 如果列值最终被 截断(表示为
...
),您需要调整Format-Table
调用,例如使用自定义列宽- 参见我的 this answer。
- 如果列值最终被 截断(表示为
运行 这针对您的示例输入在控制台中产生以下 6 列布局,输出 XPS 文档呈现类似:
MWE·-·TestFile·:·
0) Time
1) Temperature·1
2) Humidity
3) Pressure·A-B
4) Pressure·A-C
5) Pressure·D-C
0)··················· 1) 2) 3) 4) 5)
2018-07-04 12:00:00 22,03 5,34 18,93 23,10 10,10
2018-07-04 13:00:00 21,99 5,22 18,75 23,56 10,00
2018-07-04 14:00:00 21,99 5,17 18,55 23,54 10,15
2018-07-04 15:00:00 22,03 5,25 18,73 23,41 8,33