awk 如果找到模式跳过 n 行

aer*_*man 5 command-line awk text-processing

如何skip N lines在 awk 中找到模式?

awk '{if ($0~/pattern/) skip N lines; else print $0}'
Run Code Online (Sandbox Code Playgroud)

gle*_*man 10

让我向您展示如何使该 awk 解决方案更加地道(请参阅stackoverflow 上的awk 信息页面)。

从...开始:

$ seq 10 20 | awk '{if ($0 ~ /11/) {n=NR+6}; if (NR<n) next; print $0}'
10
17
18
19
20
Run Code Online (Sandbox Code Playgroud)

首先,我们将获取if语句,并将它们转换为condition {action}

awk '
    $0 ~ /11/ {n=NR+6}
    NR < n {next}
    {print $0}
'
Run Code Online (Sandbox Code Playgroud)

然后,我们将$0用作某些事情的默认值:

awk '
    /11/ {n=NR+6}
    NR < n {next}
    {print}
'
Run Code Online (Sandbox Code Playgroud)

然后,{print}如果条件为真,我们将采取默认操作

awk '
    /11/ {n=NR+6}
    NR < n {next}
    1
'
Run Code Online (Sandbox Code Playgroud)

然后,我们将反转NR < n条件以删除next

awk '
    /11/ {n=NR+6}
    NR >= n
'
Run Code Online (Sandbox Code Playgroud)

我们可以对它进行单线化:

awk '/11/ {n=NR+6} NR >= n'
Run Code Online (Sandbox Code Playgroud)

这产生相同的输出

$ seq 10 20 | awk '/11/ {n=NR+6} NR >= n'
10
17
18
19
20
Run Code Online (Sandbox Code Playgroud)

比较:

awk '{if ($0 ~ /11/) {n=NR+6}; if (NR<n) next; print $0}'
awk '/11/ {n=NR+6} NR >= n'
Run Code Online (Sandbox Code Playgroud)

作为最后一步,您可能希望将模式和 N 的值作为参数传递给 awk,这样它们就不必进行硬编码。这会使 awk 调用膨胀,但对您来说可能更灵活:

awk -v patt="11" -v N=6 '$0 ~ patt {n = NR + N} NR >= n'
Run Code Online (Sandbox Code Playgroud)

通过将参数放在 awk 脚本之后,-v可以删除,使命令更短:

awk '$0 ~ patt {n = NR + N} NR >= n' patt=11 N=6
Run Code Online (Sandbox Code Playgroud)

将变量放在 awk 主体之后的一个优点是它们可以为每个文件获得不同的值:

awk '$0 ~ patt {n = NR + N} NR >= n' patt=11 N=6 file1 N=10 file2
Run Code Online (Sandbox Code Playgroud)

  • FWIW,这里是 GNU sed 等效于您的单行化 awk 命令:``sed '/11/,+5 d'``(匹配模式 `/11/` 的行和下一行的 `5` 被删除从输出) (2认同)