【问题标题】:Use sed to fix problematic text file's lines使用 sed 修复有问题的文本文件的行
【发布时间】:2021-03-27 12:51:54
【问题描述】:

在我正在处理的自定义框架中的流水线过程中,需要处理从某个引擎生成的文件。但是,问题是某些行的文件格式有点损坏。这意味着打印行的方式不一致。像这样:

/VERY_LONG_NAME_FOR_A_SPECIFIC_ITEM_IN_THIS_PROCESS_A 
                                                             0           0        0.00 
/VERY_LONG_NAME_FOR_A_SPECIFIC_ITEM_IN_THIS_PROCESS_B
                                                             0           0        0.00 
/VERY_LONG_NAME_FOR_A_SPECIFIC_ITEM_IN_THIS_PROCESS_C 
                                                             1           1       100.00
/SLIGHTLY_SMALLER_NAME_OF_ITEM_D                             0           1        50.00
. 
. 
. 
.

我想转换成的

/VERY_LONG_NAME_FOR_A_SPECIFIC_ITEM_IN_THIS_PROCESS_A        0           0    0.00                                                            
/VERY_LONG_NAME_FOR_A_SPECIFIC_ITEM_IN_THIS_PROCESS_B        0           0    0.00 
/VERY_LONG_NAME_FOR_A_SPECIFIC_ITEM_IN_THIS_PROCESS_C        1           1    100.00
/SLIGHTLY_SMALLER_NAME_OF_ITEM_D                             0           1    50.00

这里的问题是,对于单个条目,字段 A B C 出现在 \n 之后,而对于其他条目(例如 D),该行是一致的。

通过使用一个非常有用的工具(例如,regex101),我设法构建了一个覆盖和分组行的正则表达式。正则表达式如下:

(\/.+)\n\s+([0-1]\s+[0-1]\s+.+\b)
-----  ---  ---------------------
  |     |            |
  |     |            |=> groups the secondary line containing the digits (the first two are only 0|1)
  |     |
  |     |=> new line along with all the whitespace untill the first digit 
  |
  |=> groups the first string-stream (ex: /VERY_LONG_NAME_...)

问题是我正在尝试使用(很可能以错误的方式)sed 重新创建文件:

sed -r 's/(\/.+)\n\s+([0-1]\s+[0-1]\s+.+\b)/ \1 \2/' filename.txt

这当然不像我预期的那样工作。那么我在这里做错了吗?至少在语法上是明智的?此外,我不希望修改“正确”行,这意味着没有“断”成两行的行。我只想解决“有问题”的问题

【问题讨论】:

  • 你的字段分隔符是什么?制表符还是多个空格?
  • 玩 GNU sed: sed -E '/[^[:digit:]]$/{N; s/\n//}; s/[[:space:]][[:space:]]*/\t/g' filename.txt

标签: regex text sed


【解决方案1】:

使用awkcolumn

awk 'NF==1{x=$0; getline; $0=x OFS $0} {print}' filename.txt | column -t

如果当前行只有一列 (NF==1),则将完整行保存到变量 x 并读取下一行 (getline) 并使用输出字段分隔符 (OFS) 连接最后一行 (x) ) 和当前行 ($0) 到新的当前行 ($0=x OFS $0)。

输出:

/VERY_LONG_NAME_FOR_A_SPECIFIC_ITEM_IN_THIS_PROCESS_A 0 0 0.00 /VERY_LONG_NAME_FOR_A_SPECIFIC_ITEM_IN_THIS_PROCESS_B 0 0 0.00 /VERY_LONG_NAME_FOR_A_SPECIFIC_ITEM_IN_THIS_PROCESS_C 1 1 100.00 /SLIGHTLY_SMALLER_NAME_OF_ITEM_D 0 1 50.00

见:8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR

【讨论】:

  • 但这不会“编辑”文件,对吗?我还认为,由于您使用awk,因此无法通过sed 实现所需的任务?
  • 这不会更改文件。我认为sed 会变得更加复杂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-29
  • 2014-10-11
  • 2015-10-02
  • 2013-11-01
  • 2011-01-10
相关资源
最近更新 更多