【问题标题】:Using sed, tr, ... to fix the structure of a file使用 sed, tr, ... 来修复文件的结构
【发布时间】:2014-10-11 23:21:01
【问题描述】:

我有文件的行应该是

U:<text>\tD:<text>\tA:<text>\n

其中 是一些没有制表符或换行符的文本。 \t 是制表符,\n 是换行符。不幸的是,一些 字段包含换行符,因此结构被破坏。比如这样:

U:uuu     D:ddd     A:aaa
U:uuu     D:ddd     A:aaa
U:uu
    u    D:ddd    A:aaa
U:uuu     D:ddd     A:aaa

这里在第 3 行的 U 字段中有一个换行符,导致一些应该在第 3 行的内容现在在第 4 行。如何使用 sed 或 tr 等工具修复结构?我想删除那些不在记录末尾的换行符。

所以例如上面的固定文件应该是这样的:

U:uuu     D:ddd     A:aaa
U:uuu     D:ddd     A:aaa
U:uuu     D:ddd     A:aaa
U:uuu     D:ddd     A:aaa

解决方案的另一个重要方面是速度,因为我要修复数千兆字节的文件。

【问题讨论】:

  • A: 文本是否可以包含错误的换行符? &lt;text&gt; 的任何部分是否可以包含 A:U:D:?要处理的文件有多大?将整个文件放入内存是一种选择(例如,小于 1 GiB 的文件),还是必须更零碎地完成? 'continuation' 行上是否总是有前导空格?
  • 目前我只在 U 中找到了额外的换行符。但是如果代码可以修复 D 和 A 中潜在的额外换行符,那就太好了,但如果不能,也可以。文本中不应有任何 A: U: 和 D: 。可以假设该文件可以在 RAM 中读取。我实际上有数千个文件,但每个文件最多 2GB。

标签: linux bash sed terminal tr


【解决方案1】:

给定输入数据(保存在文件data中):

U:uuu     D:ddd     A:aaa1
U:uuu     D:ddd     A:aaa2
U:uu
    u     D:ddd     A:aaa3
U:uuu     D:ddd     A:aaa4
U:uuu     D:dd
              d     A:aaa5
U:uuu     D:ddd     A:aaa6

sed 脚本(保存在文件sed.script):

/^U:.* D:.* A:.*/ { p; d; }
/^U:.* D:.*/ { N; s/\n *//; p; d; }
/^U:.*/ { N; s/\n *//; p; d; }

可以运行并产生显示的输出:

$ sed -f sed.script data
U:uuu     D:ddd     A:aaa1
U:uuu     D:ddd     A:aaa2
U:uuu     D:ddd     A:aaa3
U:uuu     D:ddd     A:aaa4
U:uuu     D:ddd     A:aaa5
U:uuu     D:ddd     A:aaa6
$

脚本的第一行在一行中查找U:D:A:,假设它是完整的(而不是损坏的A: 文本字段)并打印该行并将其删除(跳过脚本中的其他操作)。第二行仅查找U:D:A: 大概在下一行。它附加下一行输入,删除嵌入的换行符和后面的空格(如果有的话),然后像以前一样打印和删除。第三行仅查找U:,并假定D:A: 都在下一行。它追加下一行,删除嵌入的换行符和后面的空格(如果有的话),然后像以前一样打印和删除。

扩展它以处理A: 文本字段中的中断将是非常重要的。扩展它来处理也很重要:

U:uu
    u     D:dd
              d     A:aaa7

在形式上两者都不是不可能的(特别是如果您选择使用 Perl 或 Python 而不是 sed),但并非完全简单。双分处理更简单;在第三行中,您将根据是否找到 A: 等进行第二组条件操作。

处理单个字段的多个拆分:

U:u
   u
    u
           D:d
              d
               d
                      A:aaa

也会很棘手 - 可能可行,即使在 sed 中,但也很棘手。

【讨论】:

  • 效果很好!只有一点:复制脚本时,U:.*D:.* 之间可能会出现空格,应该用制表符替换。
  • 非常中肯的评论;我测试了所有空白,而不是标签。您可以将.* 替换为[^&lt;tab&gt;]*,并将D:A: 之前的空白替换为制表符;冲洗并重复。换行符后面可能还需要[[:space:]] 或附近,而不是空白星号。不过,关键在于脚本的其余部分,而不是正则表达式处理空白的细节。
  • @Jonathan VG 解释
猜你喜欢
  • 1970-01-01
  • 2020-12-29
  • 2015-04-24
  • 2023-01-13
  • 2021-03-27
  • 2014-08-23
  • 1970-01-01
  • 2015-03-19
相关资源
最近更新 更多