![计算模式匹配之前/之后的总行数](https://linux22.com/image/40532/%E8%AE%A1%E7%AE%97%E6%A8%A1%E5%BC%8F%E5%8C%B9%E9%85%8D%E4%B9%8B%E5%89%8D%2F%E4%B9%8B%E5%90%8E%E7%9A%84%E6%80%BB%E8%A1%8C%E6%95%B0.png)
我有一长串 IP 地址,但没有按顺序排列。我需要查找特定 IP 地址之前/之后有多少个 IP 地址。我怎样才能实现这个目标?
答案1
匹配之前和之后的行数,包括匹配(即,如果要排除匹配,则需要从结果中减去 1):
sed -n '0,/pattern/p' file | wc -l
sed -n '/pattern/,$p' file | wc -l
但这与 IP 地址无关。
答案2
也许最简单的是,
sed -n '/pattern/{=; q;}' file
感谢@JoshepR指出错误
答案3
我用两种方式做到了这一点,但我认为我最喜欢这个:
: $(( afterl=( lastl=$(wc -l <~/file) ) - 2 -
$(( beforel=( matchl=$(sed -n "/$IP/{=;q;}" <~/file) ) - 1
)) ))
for n in last match afters befores
do printf '%s line%s :\t%d\n' \
"${n%s}" "${n##*[!s]}" $((${n%s}l))
done
这会将所有这些保存为当前 shell 变量 - 并随后在 for 循环中评估它们以进行输出。它计算文件中的总行数wc
,并获取第一个匹配的行号sed
。
其输出:
last line : 1000
match line : 200
after lines : 799
before lines : 199
我也做了:
sed -n "/$IP/=;\$=" ~/file |
tr \\n \ | {
IFS=' ' read ml ll
printf '%s line%s:\t%d\n' \
last '' $((ll=${ll##* }))
match '' $ml \
after s "$((al=ll-ml-1)) \
before s $((bl=ml-1))
}
sed
仅打印匹配的行号和最后的行号,然后tr
将中间的\n
ewlines 转换为,并将read
第一个sed
结果读入$ml
,将所有其他结果读入$ll
。$ll
稍后再次设置时,可以通过从 的扩展中剥离除最后一个结果之外的所有结果来处理可能的多个匹配情况。
其输出:
last line : 1000
match line : 200
after lines : 799
before lines : 199
两种方法都在按以下方式生成的文件上进行了测试:
IP='some string for which I seek'
for count in 1 2 3 4 5
do printf '%.199d%s\n' 0 "$IP"
done | tr 0 \\n >~/file
确实如此,按行号:
- 设置搜索字符串
- 循环五次以确保有多个匹配项
- 打印 199 个零,然后
"$IP"
打印\n
ewline - 管道输出到
tr
- 将零转换为\n
ewlines 然后转换为~/file
答案4
awk
报告最后一场比赛之前和之后的行数的解决方案
awk '/192\.168\.1\.1/{x=NR};{y=NR} END{printf "before-%d, after-%d\n" , x-1, y-x}' file