一切都在标题中。基本上让我说我有这种模式
some text lalala
another line
much funny wow grep
我很有趣,我希望我的输出是“lalala”
谢谢
答案 0 :(得分:2)
一个可能的答案是使用ed
或ex
来执行此操作(其中很简单):
ed - yourfile <<< 'g/funny/.-2p'
(或者将ed
替换为ex
。您可能还有red
,受限制的编辑器;它无法修改文件。)这会查找模式{{1} } global,并且每当找到它时,在匹配行(即/funny/
部分)之前打印第2行。或者,如果你想在匹配'funny'的行之前包含'lalala'的最新行:
.-2p
唯一的问题是,如果您尝试处理标准输入而不是文件;然后你必须将标准输入保存到文件并处理该文件,这会破坏并发性。
你不能在ed - yourfile <<< 'g/funny/?lalala?p'
中做负偏移(虽然GNU sed
允许你做正偏移,所以你可以使用sed
让'lalala'变成'有趣'基于找到'lalala'的行(这不是你想要的),但你找不到基于找到'有趣'的'lalala'行。标准sed -n '/lalala/,+2p' file
根本不允许偏移。
如果您只需要打印在模式匹配行之前的8行上找到的IP地址,则需要一个稍微复杂一点的sed
脚本,但它仍然可行:
ed
这使用相同的基本机制来查找正确的行,然后运行替换命令以删除行上最后一个空格的所有内容并打印修改后的版本。由于没有ed - yourfile <<< 'g/funny/.-8s/.* //p'
命令,因此它实际上不会修改文件。
答案 1 :(得分:1)
由于grep -B
仅在匹配之前打印每个完整行数,因此您必须将输出通过管道输入grep或Awk。
grep -B 2 "funny" file|awk 'NR==1{print $NF; exit}'
您也可以使用Awk。
awk -v s="funny" '/[[:space:]]lalala$/{n=NR+2; o=$NF}NR==n && $0~s{print o}' file
如评论中所述,匹配前8行IP地址的具体示例:
awk -v s="funny" '
/[[:space:]][0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/ {
n=NR+8
ip=$NF
}
NR==n && $0~s {
print ip
}' file
这些Awk解决方案首先找到您可能需要的输出字段,然后仅在您想要的单词存在于n
后面的行中时打印输出。
答案 2 :(得分:0)
这是尝试略微概括的Awk解决方案。它维护最后q
行的循环队列,并在看到匹配时在队列的头部打印该行。
#!/bin/sh
: ${q=8}
e=$1
shift
awk -v q="$q" -v e="$e" '{ m[(NR%q)+1] = $0 }
$0 ~ e { print m[((NR+1)%q)+1] }' "${@--}"
适应不同的默认值(我将其设置为8)或正确的选项处理(目前,您将像q=3 ./qgrep regex file
一样运行)以及记住(并因此打印)整行应该是很容易。
(如果你在第一行q
- 1行看到一个匹配项,我也没有理由让它正常工作。那么它只会打印一个空行。)