使用 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-PrinterOut-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