【问题标题】:Linux translate blocks of text to lines of textLinux 将文本块转换为文本行
【发布时间】:2014-07-20 16:29:35
【问题描述】:

我有一个看起来像这样的文件:

ignoretext
START
a b
c d
e
END
ignoretext
START
f g h
i
END
ignoretext

我想把它翻译成以下行:

a b c d e
f g h i

【问题讨论】:

  • 好计划。你试过什么?
  • 可怕的 bash while 循环与 read LINE,并在 awk 上阅读,但无法弄清楚如何忽略开始/结束行,并将它们合并为一行让我更加偏离基础。

标签: linux bash text awk


【解决方案1】:

这是使用awk 的一种方法

awk '/END/ {ORS=RS;print "";f=0} f; /START/ {ORS=" ";f=1}' file
a b c d e
f g h i

添加了在行尾不留空格的版本。这样做可能更短

awk 'a && !/END/ {printf FS} /END/ {print "";f=a=0} f {printf "%s",$0;a++}  /START/ {f=1}'
a b c d e
f g h i

【讨论】:

  • 这个解决方案的唯一问题是它会在每行的末尾添加一个空格,如果遇到没有 START 的 END,它会打印一个空行而不是忽略它。 @DavidParks 使用 /START/,/END/ 几乎总是错误的方法,因为它使琐碎的事情稍微简单一些,但随后需要完全重写或可怕的代码重复等,即使是稍微复杂一点的事情。跨度>
  • @EdMorton 我没有看到空格:)。添加了另一个版本,只是为了好玩,没有空格。
  • 是的,每次我做这些中的一个时,我都会在测试时添加一个|tr ' ' '#',以确保它们很难被发现,有时当你错误地添加它们时它并不明显。
  • 哦,千万不要这样做printf $0,否则当输入数据包含 printf 格式化字符时,您会感到非常意外,例如%。始终使用 printf fmt,data 的完整 printf 概要(例如 printf "%s",$0)来打印输入数据。
  • 这是一个 hack,但是如果您不关心保留内部空白的细节,您可以随时通过另一个 awk 将整个内容通过管道删除周围的空白:| awk '$1=$1' 这是一个无论如何,你的工具带中都有有用的命令。
【解决方案2】:

这是使用 GNU sed 的另一个变体:

sed -n '/START/,/END/{:a;/START/d;/END/!{N;ba};s/\n/ /g;s/ END//;p}' file
a b c d e
f g h i 

以更易读的格式和解释:

sed -n '                  # Suppress default printing
/START/,/END/ {           # For the range between /START/ and /END/
    :a;                   # Create a label a
    /START/d              # If the line contains START, delete it
    /END/! {              # Until a line with END is seen
        N                 # Append the next line to pattern space
        ba                # Branch back to label a to repeat
    }
    s/\n/ /g              # Remove all new lines
    s/ END//              # Remove the END tag
    p                     # Print the pattern space
}' file

【讨论】:

    【解决方案3】:

    Jotne 的 awk 解决方案可能是最干净的,但这是使用 GNU 版本的 sed 的一种方法:

    sed -ne '/START/,/END/{/\(START\|END\)/!H}' \
         -e '/END/{s/.*//;x;s/\n/ /g;s/^ *\| *$//\p}'
    

    【讨论】:

      【解决方案4】:
      $ awk 'f{ if (/END/) {print rec; rec=sep=""; f=0} else {rec = rec sep $0; sep=" "} } /START/{f=1}' file
      a b c d e
      f g h i
      

      【讨论】:

        猜你喜欢
        • 2016-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-12
        • 2014-09-08
        • 1970-01-01
        • 2019-10-07
        • 1970-01-01
        相关资源
        最近更新 更多