我有以下代码,它将删除带有该模式的行banana
及其后的 2 行:
sed '/banana/I,+2 d' file
到目前为止,一切都很好!但我需要它删除 2 行前 banana
,但我无法用“减号”或其他任何东西来得到它(类似于应该grep -v -B2 banana file
做但没有做的事情):
teresaejunior@localhost ~ > LC_ALL=C sed '-2,/banana/I d' file
sed: invalid option -- '2'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,-2 d' file
sed: -e expression #1, char 16: unexpected `,'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,2- d' file
sed: -e expression #1, char 17: unknown command: `-'
ベストアンサー1
Sed 不会回溯:一旦处理完一行,就完成了。因此,“查找一行并打印前 N 行”不会按原样工作,这与“查找一行并打印接下来的 N 行”不同,后者很容易移植。
如果文件不太长,那么您似乎可以使用 GNU 扩展,因此可以使用tac
反转文件的行。
tac | sed '/banana/I,+2 d' | tac
另一个攻击角度是在 awk 这样的工具中维护滑动窗口。改编自grep 的 -A -B -C 开关是否有任何替代方案(在 之前和之后打印几行)?(警告:经过最低限度的测试):
#!/bin/sh
{ "exec" "awk" "-f" "$0" "$@"; } # -*-awk-*-
# The array h contains the history of lines that are eligible for being "before" lines.
# The variable skip contains the number of lines to skip.
skip { --skip }
match($0, pattern) { skip = before + after }
NR > before && !skip { print NR h[NR-before] }
{ delete h[NR-before]; h[NR] = $0 }
END { if (!skip) {for (i=NR-before+1; i<=NR; i++) print h[i]} }
用法:/path/to/script -v pattern='banana' -v before=2