sed或awk:删除模式后面的n行

时间:2010-12-09 10:05:46

标签: unix sed awk

我如何在sed中混合模式和数值范围(或任何类似的工具 - 例如awk)?我想要做的是匹配文件中的某些行,并在继续之前删除接下来的n行,我想将其作为管道的一部分。

6 个答案:

答案 0 :(得分:152)

我会去看看。

删除模式后的5行(包括带模式的行):

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

要在图案后删除5行(不包括带图案的行):

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

答案 1 :(得分:5)

简单awk解决方案:

假设用于查找匹配行的正则表达式存储在shell变量$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' 根据同名的 shell 变量定义-v regex="$regex" -v count="$count"个变量。
  • awk匹配感兴趣的线条
    • $0 ~ regex初始化跳过计数并继续到下一行,有效地跳过匹配行;在第二个解决方案中,{ skip=count; next }之前的print确保跳过。
    • next减少跳过次数,如果(仍然)> = 0则采取措施,这意味着应该跳过手边的行。
    • --skip >= 0进入下一行,有效地跳过当前行
  • { next }1的常用简写;也就是说,简单地打印当前行
    • 只有非匹配和非跳过的行才能到达此命令。
    • { print }等同于1的原因是{ print }被解释为布尔模式,根据定义,它总是计算为true,这意味着它的相关操作( block)无条件执行。由于在这种情况下存在关联操作,1默认为打印该行。

答案 2 :(得分:2)

此解决方案允许您传递“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的stdin,因此这适用于您的管道

答案 3 :(得分:2)

这可能对您有用:

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

答案 4 :(得分:2)

使用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
$

答案 5 :(得分:1)

没有GNU扩展名(例如在macOS上):

要删除图案后的5行(包括带有图案的行)

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

添加-i ''进行就地编辑。