Linux 如何像grep-B这样只选择一行?
一切都在标题里。基本上,假设我有这个图案Linux 如何像grep-B这样只选择一行?,linux,bash,shell,scripting,Linux,Bash,Shell,Scripting,一切都在标题里。基本上,假设我有这个图案 some text lalala another line much funny wow grep 我觉得很有趣,我希望我的输出是“拉拉” 谢谢你一个可能的答案是使用ed或ex来实现这一点(在它们中这是微不足道的): 唯一的问题是,如果您试图处理标准输入而不是文件;然后必须将标准输入保存到文件并处理该文件,这会破坏并发性 您不能在sed中进行负偏移(虽然GNUsed允许您进行正偏移,因此您可以使用sed-n'/lalala/,+2p'文件根据查找“l
some text lalala
another line
much funny wow grep
我觉得很有趣,我希望我的输出是“拉拉”
谢谢你一个可能的答案是使用
ed
或ex
来实现这一点(在它们中这是微不足道的):
唯一的问题是,如果您试图处理标准输入而不是文件;然后必须将标准输入保存到文件并处理该文件,这会破坏并发性
您不能在sed
中进行负偏移(虽然GNUsed
允许您进行正偏移,因此您可以使用sed-n'/lalala/,+2p'文件
根据查找“lalala”来获取“lalala”到“funcy”行(这不是您想要的),但无法根据查找“funcy”找到“lala”行。标准sed
完全不允许偏移
如果只需要打印模式匹配行之前第8行中找到的IP地址,则需要稍微复杂一点的ed
脚本,但仍然可以:
ed - yourfile <<< 'g/funny/.-8s/.* //p'
ed-yourfile由于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
对于IP地址的具体示例,如您的评论中所述,匹配前8行:
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解决方案首先找到您可能需要的输出字段,然后仅当您想要的单词存在于下一行中时才打印输出。这里尝试一种稍微通用的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中看到匹配,我也不想让它正常工作。它只会打印一个空行。)是“拉拉”还是整行?你是只想要一行写着“拉拉”呢,还是随便哪一行正好是前面两行(即使它不包含“拉拉”)?是的,只是拉拉。在我的情况下,它是一个ip地址。我所需要做的就是得到ip地址,它在我grep行的末尾上方8行。当你不习惯所有的工具,例如cut、sed、grep等时,这有点困难。我正在处理它,但这一个很困难
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
#!/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] }' "${@--}"