パターンと数値範囲をsed(または同様のツール-awkなど)でどのように混在させるのですか?私がしたいのは、ファイル内の特定の行を一致させ、先に進む前に次のn行を削除し、パイプラインの一部としてそれを実行することです。
これでやってみます。
パターンの後の5行を削除するには(パターンのある行を含む):
sed -e '/pattern/,+5d' file.txt
パターンの後の5行を削除するには(パターンのある行を除く):
sed -e '/pattern/{n;N;N;N;N;d}' file.txt
シンプルawk
ソリューション:
一致する行を見つけるために使用する正規表現は、シェル変数$regex
に格納され、スキップする行数は$count
に格納されていると仮定します。
一致する行がalsoもスキップされる($count + 1
行がスキップされる):
... | awk -v regex="$regex" -v count="$count" \
'$0 ~ regex { skip=count; next } --skip >= 0 { next } 1'
一致する行がnotをスキップする必要がある場合($count
行after マッチはスキップされます):
... | 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行。GNU拡張機能なし(例:macOS)):
パターンの後の5行を削除するには(パターンのある行を含む)
sed -e '/pattern/{N;N;N;N;d;}'
追加 -i ''
その場で編集します。
これはあなたのために働くかもしれません:
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
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の標準入力を意味するため、これはパイプラインに適しています