回答:
これでやってみます。
パターンの後の5行を削除するには(パターンのある行を含む):
sed -e '/pattern/,+5d' file.txt
パターンの後ろの5行を削除するには(パターンのある行を除く):
sed -e '/pattern/{n;N;N;N;N;d}' file.txt
/pattern/,+5
は、「パターン」を含む行で始まり(/pattern/
)、5行後に終了する()範囲を定義します+5
。最後の文字d
は、その範囲の各行で実行するコマンド、つまり「削除」です。代わりに範囲を一致させる第二のレシピでは、それは(パターンを含むだけ行に一致し/pattern/
)、次いで、一連のコマンド実行:{n;N;N;N;N;d}
、基本的に次の行を(プリントn
)した後、読み出し、最終的に次の4つのライン(廃棄N;N;N;N;d
)。
sed -e '/pattern/{n;N;N;N;N;d;}' file.txt
something
実行しますsed -E '/^something$/,$d'
。ここで、-E
POSIXの移植は、正規表現を拡張しています。
シンプルなawk
ソリューション:
一致する行の検索に使用する正規表現がシェル変数$regex
に格納され、スキップする行の数が格納されていると仮定し$count
ます。
一致する行もスキップする必要がある場合($count + 1
行はスキップされます):
... | awk -v regex="$regex" -v count="$count" \
'$0 ~ regex { skip=count; next } --skip >= 0 { next } 1'
場合、一致する行がべきではないスキップされ($count
行後のマッチはスキップされます)。
... | awk -v regex="$regex" -v count="$count" \
'$0 ~ regex { skip=count; print; next } --skip >= 0 { next } 1'
説明:
-v regex="$regex" -v count="$count"
同じ名前のシェル変数にawk
基づいて変数を定義します。$0 ~ regex
対象ラインに一致
{ skip=count; next }
スキップカウントを初期化して次の行に進み、一致する行を効果的にスキップします。2番目のソリューションでは、print
before next
はそれがスキップされないようにします。--skip >= 0
(まだ)> = 0の場合、スキップカウントをデクリメントしてアクションを実行し、手元の行をスキップする必要があることを意味します。{ next }
次の行に進み、効果的に現在の行をスキップします1
は、の一般的な省略形です{ print }
。つまり、現在の行が単に印刷されます
1
と同等であるが{ print }
それはある1
定義によって常に(ブロック)は、その関連付けられたアクションが無条件に実行されることをその手段、真と評価されていることを示すブールパターンとして解釈されます。この場合、関連付けられたアクションがないため、awk
デフォルトでは行を印刷します。これはあなたのために働くかもしれません:
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
pattern_number.txt
1列目に一致するパターンを含む2列のファイルで、2列目にはスキップする行数。最初のsed
コマンドsed
は、対応するマッチングとスキップを実行するスクリプトにファイルを変換します。このスクリプトは-f
、stdin(-
)を介して2番目のsed
コマンドに提供されます。2番目のsed
コマンドは、の出力から形成されたサンプルのアドホック入力ファイルを操作して、seq 21
それが機能することを示します。
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
$
このソリューションでは、パラメーターとして「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の標準入力を意味するため、これはパイプラインに適しています
+N
パターンはGNU拡張機能であることに注意してください。最初の変更n
にはN
、それは、パターンの行を含める作るためにあなたの第二の例では。