sed/awk 删除两个模式匹配上的换行符

sed/awk 删除两个模式匹配上的换行符

我有一个 .pem 文件,经过一些格式化后,它显示如下:

-----BEGIN
RSA
PRIVATE
KEY-----
MIIEogIBAAKCAQEAoK3D4mMIRnzPaYqHidgpBnDDzLlcYYd0GoB0pQGyGSHDW7KO3K+VeJP90GhE
ZTEWJLp2N5DR/KT+5Vg7cgdx/GCCrnlbW0McP/IvkYAuWCgbzoXH9eE+kDRtAmurBYCk7OTOwQ26
..........................LONG LONG LONG KEY................................
QRRLFsXua9spUh0yPd163IZStKZMhZBPJfMaqbi1WF+j21DdYyS0qpaZQRjFzRLvGuXeGLZG/COD
ip10XRJMMXY0m14bqOTcqKTya/5PTJIjDWC22+soIjLy0ZjWKo9n05Oal2t4q35kbos=
-----END
RSA
PRIVATE
KEY-----

我显然需要这样:

-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAoK3D4mMIRnzPaYqHidgpBnDDzLlcYYd0GoB0pQGyGSHDW7KO3K+VeJP90GhE
ZTEWJLp2N5DR/KT+5Vg7cgdx/GCCrnlbW0McP/IvkYAuWCgbzoXH9eE+kDRtAmurBYCk7OTOwQ26
..........................LONG LONG LONG KEY................................
QRRLFsXua9spUh0yPd163IZStKZMhZBPJfMaqbi1WF+j21DdYyS0qpaZQRjFzRLvGuXeGLZG/COD
ip10XRJMMXY0m14bqOTcqKTya/5PTJIjDWC22+soIjLy0ZjWKo9n05Oal2t4q35kbos=
-----END RSA PRIVATE KEY-----

我该如何使用awkor来做到这一点sed

我在网上找到的所有教程都展示了如何对整个文本或一种aaaabbbaaacccc我觉得令人困惑的模式进行操作。

我尝试过这样的事情:

tr ' ' '\n' < test.pem  | awk '/BEGIN\nRSA\nPRIVATE\n$/ { printf("%s\t", $0); next } 1' > test-format.pem

但那失败了。

我不知道这是否重要,但我是在docker 容器#!/bin/sh中的 shell 脚本中执行此操作的python:3.5-alpine

任何帮助是极大的赞赏。

答案1

一种方法是sed

sed -e '/^---/ {
  :1
  $!N
  s/\n/ /
  /---$/!b1
}' <file

这种方法可以直接完成工作:

  • 如果行以 开头---,则输入代码块
  • 在代码块内,我们创建一个名为的循环标签1
  • 如果当前行不是最后一行,我们读取N输入的分行$
  • 将换行符替换\n为空格
  • 如果下一行确实以 结尾---,则中断!循环,否则重新开始循环b1

答案2

假设关键行也应该收集在一长行中:

sed '
    :a
    N
    /\n-\|-\n/{
        P
        D
    }
    s/\n/ /
    ta
    ' file

答案3

这是另一个sed

sed '/^---/,/---$/{H;/^---/h;/---$/!d;x;s/\n/ /g;}' infile

这个使用范围和保持缓冲区。它将该范围内的每一行附加到保存缓冲区,如果它是范围的开头,则覆盖它;如果该行不是范围末尾,它将删除该行,否则它会交换缓冲区并用空格替换所有换行符。
还有一种不同的方法ed

ed -s infile <<\IN
?^---?,.-s/$/ /
?^---?,$j
1,/---$/-s/$/ /
1,/---$/j
w
q
IN

这个使用四个范围:首先它向后搜索(从ed文件末尾开始),并在第一个范围中的每行末尾附加一个空格,然后连接第二个范围中的行(实际上是第一个范围中的行加上多一行);然后它会执行相同的操作,但从文件的开头开始。

答案4

按照评论中的要求进行 posix 版本:

#!/bin/sh
jump=1

while IFS= read -r lin; do

  case $lin in 
    ----*)
        jump=0
    ;;
    *----)
        jump=1
    ;;
  esac

  if [ "$jump" = "1" ]; then 
        printf '%s\n' "$lin" 
  else
        printf '%s' "$lin "
  fi

done <"$1"

调用它:

./script file.txt >thedest.txt 

相关内容