【问题标题】:Preserving blank columns & adding delimiters when reading fixed width data读取固定宽度数据时保留空白列并添加分隔符
【发布时间】:2021-04-28 00:59:53
【问题描述】:

我正在解析一个文件。

文件格式如下:


Column1  Column2  Column3  Column4  Column5
1        2        3        4        5
6        7                 8        9
10       11       12                14
         15       16       17       18

某些列是空的。所以我正在读取两个具有与上述相同格式的文件并合并两个文件并添加“|”在每一列之间,所以它应该看起来像这样:


Column1 | Column2 | Column3 | Column4 | Column5
1       | 2       | 3       | 4       | 5
6       | 7       |         | 8       | 9
10      | 11      | 12      |         | 14
        | 15      | 16      | 17      | 18

但我越来越像这样了。列中的空格被删除。


Column1 | Column2 | Column3 | Column4 | Column5
1       | 2       | 3       | 4       | 5
6       | 7       | 8       | 9
10      | 11      | 12      | 14
15      | 16      | 17      | 18

代码部分:

while(<FH>){
   my @lines =split ' ',$_;
   say (join '|',@lines);
}

我知道这是因为我用空格分隔符分割。谁能告诉我如何获得所需的输出?

【问题讨论】:

  • 根据字符数分割
  • @JimGarrison,怎么样?你能解释更多吗?谢谢。

标签: perl text-processing


【解决方案1】:

您可以使用unpack 来解析固定宽度的数据。模板中的 A9 假定您的列是 9 个字符宽。您可以使用sprintf 将数据再次分隔到原始宽度的列中。

use warnings;
use strict;

while (<DATA>) {
    chomp;
    printf "%s\n", join '| ', map { sprintf '%-8s', $_ } unpack 'A9' x 5, $_;
}

__DATA__
Column1  Column2  Column3  Column4  Column5
1        2        3        4        5
6        7                 8        9
10       11       12                14
         15       16       17       18

打印出来:

Column1 | Column2 | Column3 | Column4 | Column5 
1       | 2       | 3       | 4       | 5       
6       | 7       |         | 8       | 9       
10      | 11      | 12      |         | 14      
        | 15      | 16      | 17      | 18      

【讨论】:

    【解决方案2】:

    如果您不需要解析数据来做任何事情,只需重新格式化它,您可以使用正则表达式替换来添加竖线字符。

    此代码将在每 9 个字符后添加| 。这假设您的数据是固定宽度的列。 \K 断言意味着保留(明白吗?)所有向左匹配的文本,而不是用替换文本替换它。因此,实际上它允许您设置将放置s/// 右侧的文本的点。 /m 选项告诉 Perl 这是一个多行字符串。 (?!$) 断言意味着“不在行尾”,因此我们不会在最后一列之后插入任何内容。

    我将所有文本都放在一个变量中,但您可以逐行进行。

    如果列是可变宽度的,您仍然可以使用正则表达式来完成,但它会变得更加复杂。 unpack/sprintf 在这种情况下可能会更简单。

    $s = '
    Column1  Column2  Column3  Column4  Column5
    1        2        3        4        5
    6        7                 8        9
    10       11       12                14
             15       16       17       18
    ';
    
    
    $s =~ s/.{9}(?!$)\K/| /gm;
    print $s;
    
    
    Column1  | Column2  | Column3  | Column4  | Column5
    1        | 2        | 3        | 4        | 5
    6        | 7        |          | 8        | 9
    10       | 11       | 12       |          | 14
             | 15       | 16       | 17       | 18
    
    

    更多信息perlre

    谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-14
      • 1970-01-01
      • 2016-05-15
      • 2012-03-16
      • 1970-01-01
      • 2012-10-21
      • 1970-01-01
      • 2019-06-14
      相关资源
      最近更新 更多