web-dev-qa-db-ja.com

sed / START /、/ END /から最初と最後の行を除外する

入力について考えてみましょう。

=sec1=
some-line
some-other-line

foo
bar=baz

=sec2=
c=baz

= sec1 =のみを処理したい場合は、たとえば、次の方法でセクションをコメントアウトできます。

sed -e '/=sec1=/,/=[a-z]*=/s:^:#:' < input

... よくほとんど。

これにより、行がコメント化されますinclude "= sec1 ="および "= sec2 ="行、結果は次のようになります。

#=sec1=
#some-line
#some-other-line
#
#foo
#bar=baz
#
#=sec2=
c=baz

私の質問は:sedの/ START /、/ END /範囲から開始行と終了行を除外する最も簡単な方法は何ですか?

多くの場合、「s :::」の爪を改良することでこの特定のケースで解決策が得られることを私は知っていますが、私はここで一般的な解決策を求めています。

" Sed-はじめにとチュートリアル " Bruce Barnettは次のように書いています:「コマンドを制限する方法を後で説明しますが、指定されたパターンを含む行は含まれません。」彼が実際にこれを示している場所を見つけることができます。

" SEDの便利な1行のスクリプト " Eric Pementが編集したものでは、包括的な例しか見つかりませんでした。

# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p'             # case sensitive
44
Chen Levy

これでうまくいくはずです:

sed -e '/=sec1=/,/=sec2=/ { /=sec1=/b; /=sec2=/b; s/^/#/ }' < input

これはsec1とsec2の間で包括的に一致し、bコマンドで最初と最後の行をスキップします。これにより、sec1とsec2(排他的)の間に必要な行が残り、sコマンドはコメント記号を追加します。

残念ながら、区切り文字を一致させるために正規表現を繰り返す必要があります。私の知る限り、これを行うためのより良い方法はありません。少なくとも、正規表現は2回使用されていても、クリーンに保つことができます。

これは SED FAQ:RE1とRE2の間の、行自体を除くすべての行に対処するにはどうすればよいですか?

38
Ville Laurikari

範囲外の行には興味がないが、質問からのアイオワ/モンタナの例の非包括的バリアントが必要な場合(これが私をここに連れてきたものです)、「最初と最後を除いて」と書くことができます2番目のsedで簡単に「行の一致」句:

sed -n '/PATTERN1/,/PATTERN2/p' < input | sed '1d;$d'

個人的には、これは同等のものよりもわずかに明確です(大きなファイルでは遅くなりますが)

sed -n '1,/PATTERN1/d;/PATTERN2/q;p' < input

13
Paul Whittaker

別の方法は

sed '/begin/,/end/ {
       /begin/n
       /end/ !p
     }'

/begin/n->「開始」パターンの行をスキップします
/end/ !p->「終了」パターンを持たないすべての行を印刷します

Bruce Barnettのsedチュートリアルからの抜粋 http://www.grymoire.com/Unix/Sed.html#toc-uh-35a

7
MikhailVS

私が使用した:

sed '/begin/,/end/{/begin\|end/!p}'

これにより、パターン間のすべての行が検索され、パターンを含まないものがすべて印刷されます。

2
Maxim_united

awkを使用することもできます

awk '/sec1/{f=1;print;next}f && !/sec2/{ $0="#"$0}/sec2/{f=0}1' file
1
ghostdog74