用字符替换列中的空白

时间:2018-09-07 04:58:29

标签: unix awk sed

我的文件如下:

overlay

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

使用awk命令执行此操作时面临的问题是字段分隔符在每一行中都在不断变化。

我到目前为止所做的事情: 我提取了具有某些字段模式的行,并将它们放置在不同的文件中。例如:我将方案3,6和9放在一个文件中,其余的放在另一个文件中,以使处理数据更加容易。我现在拥有的是:

文件1:

aufs

文件2:

overlay2

预期输出:

  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(将awk与FIELDWIDTHS结合使用):

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

案例2(使用sed命令):

  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

3 个答案:

答案 0 :(得分: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 :(得分: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 ""}'

答案 2 :(得分:1)

使用GNU awk和while(m_running) { sd_bus_message *m = NULL; r = sd_bus_process(m_bus, &m); if (r < 0) { //error handling } r = sd_bus_wait(m_bus, (uint64_t)-1); if (r < 0) { //error handling } } 变量根据字段长度分割字段:

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。如果没有,则该字段保持不变。