删除从第 n 次出现到文件末尾

删除从第 n 次出现到文件末尾

如何使用诸如 之类的命令行工具删除从第 n 次出现的模式到文件末尾的内容sed?例如,从以下
第三个中删除:foo

something
foo1
maybe something else
foo2
maybe not
foo3 -this line and anything after is gone- 
I'm not here

$sed '/magic/'

期望的结果:

something
foo1
maybe something else
foo2
maybe not

相同的事情可以获得奖励积分,但保留包含第三个的行foo

答案1

不保留线路:

awk -v n=3 '/foo/{n--}; n > 0'

保持线路:

awk -v n=3 'n > 0; /foo/{n--}'

尽管我们可能想稍微改进一下,以便我们一找到第三个就退出并停止阅读foo

awk -v n=3 '/foo/{n--; if (!n) exit}; {print}' # not-keep
awk -v n=3 '{print}; /foo/{n--; if (!n) exit}' # keep

sed会比较麻烦。您需要将 foo 出现次数保留为保留空间中的字符数,例如:

保持:

sed '
  /foo/{
    x;s/^/x/
    /x\{3\}/{
      x;q
    }
    x
  }'

不保留:

sed -ne '/foo/{x;s/^/x/;/x\{3\}/q;x;}' -e p

答案2

如果您接受perl作为命令行工具, 你也可以

perl -ne 'print unless $c>2; ++$c if /foo/' 
perl -ne '++$c if /foo/; print unless $c>2' 

有/无保留。

答案3

替代答案:你可以从 vim 中做到这一点。您可以使用 vim 作为文本编辑器或命令行工具来完成此操作。作为文本编辑器(带或不带行):

/foo<cr>2ndG:wq<cr>
/foo<cr>2njdG:wq<cr>

一些重要的细节:<cr>意思是“输入”。另外,您通常应该<n-1>ndG在“第 N”次出现后删除。你要求 3,所以我在示例中写了 2。

您也可以纯粹从命令行执行此操作。

vim -c "/foo" -c "normal 2ndG" -c "wq"
vim -c "/foo" -c "normal 2njdG" -c "wq"

此方法也适用于正则表达式。这个网站很好地解释了正则表达式的 vim 风格。

相关内容