「スタートモード」 - 「ストップモード」ペアが最初に発生した後にテキストを印刷するにはどうすればよいですか?

「スタートモード」 - 「ストップモード」ペアが最初に発生した後にテキストを印刷するにはどうすればよいですか?

複数の証明書を含むファイルがあります。

-----BEGIN CERTIFICATE-----
AAAAAAA
AAAAAAA
AAAAAAA
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
BBBBBBB
BBBBBBB
BBBBBBB
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
CCCCCCC
CCCCCCC
CCCCCCC
-----END CERTIFICATE-----

AB C中に文字があるのをカットしてただ…n証明書だけを受けたいです。

それは非常に似ていますこの問題これを行うためのポータブルな方法があればと思います。sed可能であれば一緒に使用することをお勧めしますが、awk不可能な場合は使用可能ですsed

最初の出現以外の特定の値までsedを印刷する方法はありますか?

答え1

入力が正しい形式の証明書ファイルである場合(例のように)、私が考える最も簡単な方法は、次のコマンドを使用することですawk

awk '$0=="-----BEGIN CERTIFICATE-----" {n++} n>1' test.cert 

nこれは、現在の行()が「開始パターン」と正確に一致するたびに$0カウンタ変数をインクリメントします。 「見えない」ブール式がn>1trueの場合、つまり開始パターンの2番目の発生から始まると、現在の行が印刷されます。awk初期化されていない変数は0(または使用状況に応じて空の文字列)として扱われるため、nセクションで明示的に初期化する必要はありません。0BEGIN

入力文書が破損すると、状況がより複雑になります。言い換えれば、終了パターンに誤って一致する開始パターンが含まれている場合、またはその逆の場合も同様です。

答え2

@AdminBeeの答えは正しいアプローチですが、省略したい部分がわからない場合最初sed次のようにすることもできます。

sed -n '/^-*END CERTIFICATE-*$/!d;:a n;p;ba' file

または複数行に移植可能な方法で:

sed -n '
    /^-*END CERTIFICATE-*$/!d;:a
    n;p;ba
' file

sed最初の行が見つかるまですべての行を削除し、他のすべての行を-----END CERTIFICATE-----食べて印刷するループを作成します。

答え3

正規表現 /BEGIN/ および /END/ を必須に変更する必要があります。

awk '
/BEGIN/,/END/{
  if ( /END/ && !f++ ) next
}f
' file

perl喫煙モード(-0777

perl -0777 -pe '
  my($b,$e) = map { quotemeta s/$/ CERTIFICATE/r } qw(BEGIN END);
  my($B,$E) = map { qr{^-+ $_ -+\n}mx } ($b,$e);
  my $re = qr{$B (?s:.*?) $E}mx;
  substr($_,0,$+[0],"") if m{$re}m;
' file

GNU sedエディタ

sed -ne 's/\n//;t2
  /BEGIN/!{$!N;D;}
  :1;n;/END/!b1
  n
  :2;$!{N;P;G;D;}
  p
' file

csplitここではLinuxユーティリティも利用できます。まず、END行の周りに入力ファイルをチャンクします。その後、BEGiNの前にENDが表示された場合は、最初のファイルまたは2つのファイルを削除します。

csplit -sz file '/END/+1' '{*}'
for f in xx*;do
  sed -n '/BEGIN/,/END/!d;$Q1' $f
  status=$?; rm -- "$f"
  [ " $status" = ' 1' ] && break
done
printf '%s\n' xx* | xargs -r cat

関連情報