複数の証明書を含むファイルがあります。
-----BEGIN CERTIFICATE-----
AAAAAAA
AAAAAAA
AAAAAAA
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
BBBBBBB
BBBBBBB
BBBBBBB
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
CCCCCCC
CCCCCCC
CCCCCCC
-----END CERTIFICATE-----
A
B
C
中に文字があるのをカットしてただ…n
証明書だけを受けたいです。
それは非常に似ていますこの問題これを行うためのポータブルな方法があればと思います。sed
可能であれば一緒に使用することをお勧めしますが、awk
不可能な場合は使用可能ですsed
。
最初の出現以外の特定の値までsedを印刷する方法はありますか?
答え1
入力が正しい形式の証明書ファイルである場合(例のように)、私が考える最も簡単な方法は、次のコマンドを使用することですawk
。
awk '$0=="-----BEGIN CERTIFICATE-----" {n++} n>1' test.cert
n
これは、現在の行()が「開始パターン」と正確に一致するたびに$0
カウンタ変数をインクリメントします。 「見えない」ブール式がn>1
trueの場合、つまり開始パターンの2番目の発生から始まると、現在の行が印刷されます。awk
初期化されていない変数は0(または使用状況に応じて空の文字列)として扱われるため、n
セクションで明示的に初期化する必要はありません。0
BEGIN
入力文書が破損すると、状況がより複雑になります。言い換えれば、終了パターンに誤って一致する開始パターンが含まれている場合、またはその逆の場合も同様です。
答え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