用字符替换列中的空格

问题描述 投票:1回答:3

我的文件看起来像这样:

  Scenario 1                                     0.20          0.00     0.00 r
  Scenario 2                                     0.08          0.34 &   0.34 r
  Scenario 3                          6   12.95 
  Scenario 4                              0.00   0.08   0.00   0.00 &   0.35 r
  Scenario 5                                     0.07          0.08 &   0.42 r
  Scenario 6                          6   8.70 
  Scenario 7                              0.00   0.07   0.00   0.00 &   0.42 r
  Scenario 8                                     0.31          0.28 &   0.70 f
  Scenario 9                          5   5.06 

我的目标是:使用“ - ”替换空单元格/空格/缺少值的列(总共有8个字段)

我使用awk命令执行此操作时遇到的问题是字段分隔符随着每一行而不断变化。

到目前为止我做了什么:我已经提取了具有某些字段模式的行并将它们放在不同的文件中。例如:我已将场景3,6和9放在一个文件中,其余放在另一个文件中,以便更容易处理数据。我现在拥有的是:

档案1:

Scenario 3                          6   12.95
Scenario 6                          6   8.70
Scenario 9                          5   5.06

文件2:

  Scenario 1                                     0.20          0.00     0.00 r
  Scenario 2                                     0.08          0.34 &   0.34 r

  Scenario 4                              0.00   0.08   0.00   0.00 &   0.35 r
  Scenario 5                                     0.07          0.08 &   0.42 r

  Scenario 7                              0.00   0.07   0.00   0.00 &   0.42 r
  Scenario 8                                     0.31          0.28 &   0.70 f

预期产量:

  Scenario 1                          -     -    0.20    -     0.00     0.00 r
  Scenario 2                          -     -    0.08    -     0.34 &   0.34 r
  Scenario 3                          6   12.95   -      -      -        -
  Scenario 4                          -   0.00   0.08   0.00   0.00 &   0.35 r
  Scenario 5                          -     -    0.07    -     0.08 &   0.42 r
  Scenario 6                          6   8.70    -      -      -        -
  Scenario 7                          -   0.00   0.07   0.00   0.00 &   0.42 r
  Scenario 8                          -     -    0.31          0.28 &   0.70 f
  Scenario 9                          5   5.06    -      -      -        -

案例1(使用带有FIELDWIDTHS的awk):

  $ awk 'BEGIN { FIELDWIDTHS="37 3 7 7 7 9 9 "} {for(i=1;i<=NF;++i){printf $i"|"};print""}' main1.txt

| I_BLENDER_0/R_137/CLK (SDFFX2_HVT) |   |       |  0.20 |       |  0.00   |  0.00 r
| I_BLENDER_0/R_137/Q (SDFFX2_HVT)   |   |       |  0.08 |       |  0.34 & |  0.34 r
| I_BLENDER_0/n2757 (net)            | 6 |  12.95|
| I_BLENDER_0/U4847/A1 (AND2X1_LVT)  |   |  0.00 |  0.08 |  0.00 |  0.00 & |  0.35 r
| I_BLENDER_0/U4847/Y (AND2X1_LVT)   |   |       |  0.07 |       |  0.08 & |  0.42 r
| I_BLENDER_0/n2616 (net)            | 6 |  8.70 |
| I_BLENDER_0/U1/A4 (NAND4X0_HVT)    |   |  0.00 |  0.07 |  0.00 |  0.00 & |  0.42 r
| I_BLENDER_0/U1/Y (NAND4X0_HVT)     |   |       |  0.31 |       |  0.28 & |  0.70 f

案例2(使用sed命令):

  $  sed "s/^\(.\{,36\}\)$/\1`echo -$_{1..30}|tr -d '-'`/;
      s/^\(.\{38\}\) /\1-/;
      s/^\(.\{43\}\) /\1-/;
      s/^\(.\{50\}\) /\1-/;
      s/^\(.\{57\}\) /\1-/;
      s/^\(.\{64\}\) /\1-/;
      s/^\(.\{73\}\) /\1-/;
      s/ *$//"



  I_BLENDER_0/R_137/CLK (SDFFX2_HVT)  -    -     0.20    -     0.00     0.00 r
  I_BLENDER_0/R_137/Q (SDFFX2_HVT)    -    -     0.08    -     0.34 &   0.34 r
  I_BLENDER_0/n2757 (net)             6   12.95
  I_BLENDER_0/U4847/A1 (AND2X1_LVT)   -   0.00   0.08   0.00   0.00 &   0.35 r
  I_BLENDER_0/U4847/Y (AND2X1_LVT)    -    -     0.07    -     0.08 &   0.42 r
  I_BLENDER_0/n2616 (net)             6   8.70
unix awk sed
3个回答
1
投票

为此,您可以在Gnu awk中使用FIELDWIDTHS

基本上,我们将您的线条分成恒定宽度的字段。以下显示正确分割线条:

$ awk 'BEGIN{ FIELDWIDTHS="13 25 2 7 7 7 9 9"}
       {for(i=1;i<=NF;++i){printf $i"|"};print""}' file

  Scenario 1 |                        |   |       |  0.20 |       |  0.00   |  0.00 r|
  Scenario 2 |                        |   |       |  0.08 |       |  0.34 & |  0.34 r|
  Scenario 3 |                        | 6 |  12.95| ||||
  Scenario 4 |                        |   |  0.00 |  0.08 |  0.00 |  0.00 & |  0.35 r|
  Scenario 5 |                        |   |       |  0.07 |       |  0.08 & |  0.42 r|
  Scenario 6 |                        | 6 |  8.70 |||||
  Scenario 7 |                        |   |  0.00 |  0.07 |  0.00 |  0.00 & |  0.42 r|
  Scenario 8 |                        |   |       |  0.31 |       |  0.28 & |  0.70 f|
  Scenario 9 |                        | 5 |  5.06 |||||

所以我们需要做的就是在需要时用短划线替换空字段。

$ awk 'BEGIN{ FIELDWIDTHS="13 24 3 7 7 7 9 9"}
       {s=$1$2}
       {s=s ($3~/^[[:blank:]]*$/?" - ":$3)}
       {s=s ($4~/^[[:blank:]]*$/?"   -   ":$4)}
       {s=s ($5~/^[[:blank:]]*$/?"   -   ":$5)}
       {s=s ($6~/^[[:blank:]]*$/?"   -   ":$6)}
       {s=s ($7~/^[[:blank:]]*$/?"   -     ":$7)}
       {s=s ($8~/^[[:blank:]]*$/?"   -     ":$8)}
       {print s}' file

这给了:

  Scenario 1                          -    -     0.20    -     0.00     0.00 r
  Scenario 2                          -    -     0.08    -     0.34 &   0.34 r
  Scenario 3                          6   12.95   -      -      -        -     
  Scenario 4                          -   0.00   0.08   0.00   0.00 &   0.35 r
  Scenario 5                          -    -     0.07    -     0.08 &   0.42 r
  Scenario 6                          6   8.70    -      -      -        -     
  Scenario 7                          -   0.00   0.07   0.00   0.00 &   0.42 r
  Scenario 8                          -    -     0.31    -     0.28 &   0.70 f
  Scenario 9                          5   5.06    -      -      -        -     

备注:

  • 最好使用用于设置这些文件的真实格式。
  • 我总是在田地前留一个额外的空间来解释可能的减号
  • 看起来像浮点数是用%-5.2f格式编写的。这就是为什么数字12.95不对齐。 (%6.2f会更好)

注意:如果你玩一下,你实际上可以做得更短。但你有点失去了对正在发生的事情的感觉。

awk 'BEGIN{ FIELDWIDTHS="13 23 5 7 7 7 9 9"} 
     {for(i=3;i<=NF;++i)$i=$i~/^[[:blank:]]*$/?"  -":$i}
     {printf "%-13s%-23s%-5s%-7s%-7s%-7s%-9s%-9s\n",$1,$2,$3,$4,$5,$6,$7,$8}' file

甚至更短

awk 'BEGIN{ FIELDWIDTHS="36 5 7 7 7 9 9"; split(FIELDWIDTHS,a)}
     {for(i=1;i<=NF;++i) printf "%-*s",a[i], ($i~/^ *$/?"  -":$i); print ""}'

1
投票

不幸的是,在这种情况下,您需要仔细计算字符列。以下是您提供的输入代码 - 您可能需要调整实际输入文件的数字。

sed "s/^\(.\{,78\}\)$/\1`echo -$_{1..78}|tr -d '-'`/;
  s/^\(.\{38\}\) /\1-/;
  s/^\(.\{43\}\) /\1-/;
  s/^\(.\{50\}\) /\1-/;
  s/^\(.\{57\}\) /\1-/;
  s/^\(.\{64\}\) /\1-/;
  s/^\(.\{73\}\) /\1-/;
  s/ *$//" input_file

这里,第一行在行尾添加空格,以防行在到达78个字符之前终止 - 然后由替换利用。在链替换的最后,删除任何尾随空格。

第一行中看起来凌乱的表达式echo -$_{1..78}|tr -d '-'只产生了78个空格。您可能只想用一长串空格替换它。


1
投票

使用GNU awk和FIELDWIDTHS变量根据字段长度分割字段:

awk 'BEGIN{
      FIELDWIDTHS="38 4 7 7 7 9 6"
      colnr=split(FIELDWIDTHS,a," ")
    } 
    {
      for(i=1;i<=colnr;i++){
        $i=sprintf("%-"a[i]"s",((!$i&&$i!=0)||$i~/^ *$/?"-":$i))
      }
    }1' file
  Scenario 1                           -    -       0.20    -       0.00      0.00 r
  Scenario 2                           -    -       0.08    -       0.34 &    0.34 r
  Scenario 3                           6    12.95   -       -       -         -
  Scenario 4                           -    0.00    0.08    0.00    0.00 &    0.35 r
  Scenario 5                           -    -       0.07    -       0.08 &    0.42 r
  Scenario 6                           6    8.70    -       -       -         -
  Scenario 7                           -    0.00    0.07    0.00    0.00 &    0.42 r
  Scenario 8                           -    -       0.31    -       0.28 &    0.70 f
  Scenario 9                           5    5.06    -       -       -         -

BEGIN块将数组a设置为所有字段的长度,并将字段数存储在变量colnr中。

默认块循环遍历所有字段并使用sprintf()函数重写它们。 如果该字段仅包含空白$i~/^ *$/或不存在!$i&&$i!=0,请将其替换为-。如果没有,该领域保持不变。

© www.soinside.com 2019 - 2024. All rights reserved.