web-dev-qa-db-ja.com

sedまたはawk:パターンに続くn行を削除します

パターンと数値範囲をsed(または同様のツール-awkなど)でどのように混在させるのですか?私がしたいのは、ファイル内の特定の行を一致させ、先に進む前に次のn行を削除し、パイプラインの一部としてそれを実行することです。

89
Martin DeMello

これでやってみます。

パターンの後の5行を削除するには(パターンのある行を含む):

sed -e '/pattern/,+5d' file.txt

パターンの後の5行を削除するには(パターンのある行を除く):

sed -e '/pattern/{n;N;N;N;N;d}' file.txt
159
dogbane

シンプルawkソリューション:

一致する行を見つけるために使用する正規表現は、シェル変数$regexに格納され、スキップする行数は$countに格納されていると仮定します。

一致する行がalsoもスキップされる$count + 1行がスキップされる):

... | awk -v regex="$regex" -v count="$count" \
  '$0 ~ regex { skip=count; next } --skip >= 0 { next } 1'

一致する行がnotをスキップする必要がある場合$countafter マッチはスキップされます):

... | awk -v regex="$regex" -v count="$count" \
  '$0 ~ regex { skip=count; print; next } --skip >= 0 { next } 1'

説明:

  • -v regex="$regex" -v count="$count"は、同じ名前のShell変数に基づいてawk変数を定義します。
  • $0 ~ regexは対象の行と一致します
    • { skip=count; next }はスキップカウントを初期化し、次の行に進み、一致する行を効果的にスキップします。 2番目のソリューションでは、printの前のnextにより、notがスキップされます。
    • --skip >= 0は、スキップカウントをデクリメントし、(まだ)> = 0の場合にアクションを実行します。これは、手元の行をスキップすることを意味します。
    • { next }は次の行に進み、現在の行を事実上スキップします
  • 1は、{ print }の一般的な省略表現です。つまり、現在の行は単に印刷されます
    • 一致しない行とスキップされない行のみがこのコマンドに到達します。
    • 1{ print }と同等である理由は、1が、定義により常にtrueと評価されるブールパターンとして解釈されるためです。つまり、関連するアクション(ブロック)が無条件に実行されます。この場合、noに関連付けられたアクションがあるため、awkのデフォルトはprinting行。
5
mklement0

GNU拡張機能なし(例:macOS)):

パターンの後の5行を削除するには(パターンのある行を含む)

 sed -e '/pattern/{N;N;N;N;d;}'

追加 -i ''その場で編集します。

4
thakis

これはあなたのために働くかもしれません:

cat <<! >pattern_number.txt
> 5 3
> 10 1
> 15 5
> !
sed 's|\(\S*\) \(\S*\)|/\1/,+\2{//!d}|' pattern_number.txt |
sed -f - <(seq 21)
1 
2
3
4
5
9
10
12
13
14
15
21
2
potong

Perlを使用する

$ cat delete_5lines.txt
1
2
3
4
5 hello
6
7
8
9
10
11 hai
$ Perl -ne ' BEGIN{$y=1} $y=$.  if /hello/ ; print if $y==1 or $.-$y > 5 ' delete_5lines.txt
1
2
3
4
11 hai
$
2
stack0114106

このソリューションでは、パラメーターとして「n」を渡すことができ、ファイルからパターンを読み取ります。

awk -v n=5 '
    NR == FNR {pattern[$0]; next}
    {
        for (patt in pattern) {
            if ($0 ~ patt) {
                print # remove if you want to exclude a matched line
                for (i=0; i<n; i++) getline
                next
            }
        }
        print
    }
' file.with.patterns -

「-」という名前のファイルはawkの標準入力を意味するため、これはパイプラインに適しています

2
glenn jackman