grep 的 A 的倒数
Inverse of grep's A
我知道我可以用 grep
和 -A1
打印匹配项的 "next" 行,但是反过来呢?我是说,"hide the next line after a filter match".
示例:
a
b
c
d
e
cat letters.txt | grep -A1 -v "c"
<-- 隐藏 "c" 和 "d"
grep
本身并不(通常)提供此功能,但使用 Awk 或 sed
.
就足够简单了
awk '/c/ { skip=1; next }
skip { skip=0; next } 1' letters.txt
你可以用 sed
这样
sed -ne '/c/{n;d;}; p' letters.txt
这将读取文件 letters.txt
。任何与 c
不匹配的行都将被打印,如果 c
匹配,则不打印它,并转到下一行并将其从输出
中删除
使用 GNU sed 可以更容易地获得 N 行,它可以像
sed -ne '/c/,+1d; p;' letters.txt
并且您可以将 1
更改为您喜欢的任何数字。此外,您可以将 -i
标志添加到 sed
以使其在适当的位置修改文件,如果您想这样做的话
使用 awk 还可以:
awk -v s='c' '[=10=] ~ s {getline;next} 1' letters.txt
a
b
e
此答案着眼于一般 解决方案,其中变量 跳过计数。
如果你有 GNU sed
, 是最简单的解决方案。
可以稍微简化为sed '/c/,+1d'
,或者,概括为:
regex='c' count=2
sed "/${regex}/,+${count}d" letters.txt # skips c, d, e
上下文地址的 +<n>
形式与范围 开始的第 <n>
行 匹配(因此是范围 到 以下 <n>
行)是 GNU sed
扩展。
注意 $count
+1 行被跳过:匹配正则表达式的行 + $count
行 after.
为了便携性和为了更灵活(比如不跳过匹配行本身),使用 :
的通用版本
awk -v regex='c' -v count=2 \
'[=11=] ~ regex { skip=count; next } --skip >= 0 { next } 1' letters.txt # skips c, d, e
注意 $count
+1 行被跳过:匹配正则表达式的行 + $count
行 after.
-v regex='c' -v count=2
定义 awk
个具有指定值的变量。
[=26=] ~ regex
匹配感兴趣的行
{ skip=count; next }
初始化跳过计数并进行到下一行,有效地跳过匹配行;在第二个解决方案中,next
之前的 print
确保它被 不 跳过。
--skip >= 0
减少跳过计数并在它(仍然)>= 0 时采取行动,这意味着应该跳过手头的行。
{ next }
前进到下一行,有效地跳过当前行
1
是{ print }
常用的shorthand;也就是说,只打印当前行
- 只有不匹配和未跳过的行才能到达此命令。
1
等同于 { print }
的原因是 1
被解释为布尔模式,根据定义总是计算为真,这意味着其关联的操作(块)无条件执行。由于在这种情况下没有关联操作,awk
默认为打印该行。
作为符合 POSIX 的 shell 函数:
# SYNOPSIS
# matchAndSkip regex skipCount [file]
matchAndSkip() {
awk -v regex="" -v count="" \
'[=12=] ~ regex { skip=count; next } --skip >= 0 { next } 1' "${3-/dev/stdin}"
}
我知道我可以用 grep
和 -A1
打印匹配项的 "next" 行,但是反过来呢?我是说,"hide the next line after a filter match".
示例:
a
b
c
d
e
cat letters.txt | grep -A1 -v "c"
<-- 隐藏 "c" 和 "d"
grep
本身并不(通常)提供此功能,但使用 Awk 或 sed
.
awk '/c/ { skip=1; next }
skip { skip=0; next } 1' letters.txt
你可以用 sed
这样
sed -ne '/c/{n;d;}; p' letters.txt
这将读取文件 letters.txt
。任何与 c
不匹配的行都将被打印,如果 c
匹配,则不打印它,并转到下一行并将其从输出
使用 GNU sed 可以更容易地获得 N 行,它可以像
sed -ne '/c/,+1d; p;' letters.txt
并且您可以将 1
更改为您喜欢的任何数字。此外,您可以将 -i
标志添加到 sed
以使其在适当的位置修改文件,如果您想这样做的话
使用 awk 还可以:
awk -v s='c' '[=10=] ~ s {getline;next} 1' letters.txt
a
b
e
此答案着眼于一般 解决方案,其中变量 跳过计数。
如果你有 GNU sed
,
可以稍微简化为sed '/c/,+1d'
,或者,概括为:
regex='c' count=2
sed "/${regex}/,+${count}d" letters.txt # skips c, d, e
上下文地址的 +<n>
形式与范围 开始的第 <n>
行 匹配(因此是范围 到 以下 <n>
行)是 GNU sed
扩展。
注意 $count
+1 行被跳过:匹配正则表达式的行 + $count
行 after.
为了便携性和为了更灵活(比如不跳过匹配行本身),使用
awk -v regex='c' -v count=2 \
'[=11=] ~ regex { skip=count; next } --skip >= 0 { next } 1' letters.txt # skips c, d, e
注意 $count
+1 行被跳过:匹配正则表达式的行 + $count
行 after.
-v regex='c' -v count=2
定义awk
个具有指定值的变量。[=26=] ~ regex
匹配感兴趣的行{ skip=count; next }
初始化跳过计数并进行到下一行,有效地跳过匹配行;在第二个解决方案中,next
之前的print
确保它被 不 跳过。--skip >= 0
减少跳过计数并在它(仍然)>= 0 时采取行动,这意味着应该跳过手头的行。{ next }
前进到下一行,有效地跳过当前行
1
是{ print }
常用的shorthand;也就是说,只打印当前行- 只有不匹配和未跳过的行才能到达此命令。
1
等同于{ print }
的原因是1
被解释为布尔模式,根据定义总是计算为真,这意味着其关联的操作(块)无条件执行。由于在这种情况下没有关联操作,awk
默认为打印该行。
作为符合 POSIX 的 shell 函数:
# SYNOPSIS
# matchAndSkip regex skipCount [file]
matchAndSkip() {
awk -v regex="" -v count="" \
'[=12=] ~ regex { skip=count; next } --skip >= 0 { next } 1' "${3-/dev/stdin}"
}