使用 OPEN STEP 4.2 操作系统...我目前使用以下sed命令:
sed -n '1,/141.299.99.1/p' TESTFILE | tail -3
Run Code Online (Sandbox Code Playgroud)
此命令将在文件中找到一个 ip 为 141.299.99.1 的实例,并在它之前包含 3 行,这一切都很好,除了我还想找到 IP 的所有实例和它之前的 3 行而不仅仅是第一个。
有了sed你可以做一个滑动窗口。
sed '1N;$!N;/141.299.99.1/P;D'
Run Code Online (Sandbox Code Playgroud)
这样做。但要注意 -即使引用时也会bash扩张的疯狂行为! !!!从您的命令历史记录中输入命令字符串可能会使它变得有点疯狂。set +H;如果您发现是这种情况,请在命令前加上前缀。然后重新启用它(但为什么?)set -H之后再做。
那当然,只会如果应用被使用bash-尽管我不相信你。我相当确定您正在使用csh- (这恰好是 shell 其疯狂行为bash模拟历史扩展,但可能不是 c shell 所采取的极端)。所以,大概一\!应工作。我希望。
都是可移植的代码:POSIX 这样描述了它的三个运算符:(尽管值得注意的是,我仅确认早在 2001 年就存在此描述)
[2addr]N将输入的下一行(减去其终止\newline)附加到模式空间,使用嵌入的\newline 将附加材料与原始材料分开。请注意,当前行号会发生变化。
[2addr]P将模式空间(直到第一个\newline)写入标准输出。
[2addr]D通过第一个\newline删除模式空间的初始段并开始下一个循环。
所以在第一行你向模式空间添加了额外的一行,所以它看起来像这样:
^line 1s contents\nline 2s contents$
Run Code Online (Sandbox Code Playgroud)
然后在第一行和之后的每一行——除了最后一行——你添加另一行到模式空间。所以它看起来像这样:
^line 1\nline 2\nline 3$
Run Code Online (Sandbox Code Playgroud)
如果在您的内部找到了您的 ip 地址P,则将其打印到第一个换行符,因此请在此处输入第 1 行。在每个周期结束时,您都D删除相同的内容并重新开始。所以下一个循环看起来像:
^line 2\nline 3\nline 4$
Run Code Online (Sandbox Code Playgroud)
...等等。如果要在这三个中的任何一个上找到您的 ip,最旧的将打印出来 - 每次。所以你总是只领先三行。
这是一个快速示例。我将为每个以零结尾的数字打印一个三行缓冲区:
seq 10 52 | sed '1N;$!N;/0\(\n\|$\)/P;D'
10
18
19
20
28
29
30
38
39
40
48
49
50
Run Code Online (Sandbox Code Playgroud)
那比你的情况稍微复杂一点,因为我必须从0\n换行符或0$模式空间的结尾交替以更接近你的问题 - 但它们有微妙的不同,因为这需要一个锚点 - 这可能有点难以做到,因为模式空间不断变化。
我使用了 10 和 52 的奇数情况来表明只要锚点是灵活的,那么输出也是如此。完全可移植,我可以通过依靠算法来实现相同的结果并执行以下操作:
seq 10 52 | sed '1N;$!N;/[90]\n/P;D'
Run Code Online (Sandbox Code Playgroud)
并在限制我的窗口的同时扩大搜索范围 - 从 0 到 9 和 0,从 3 行到 2 行。
无论如何,你明白了。
这里尝试grep -B3使用 sed 移动窗口进行模拟,基于此 GNU sed 示例(但希望符合 POSIX 标准 - 感谢 @St\xc3\xa9phaneChazelas):
sed -e \'1h;2,4{;H;g;}\' -e \'1,3d\' -e \'/141\\.299\\.99\\.1/P\' -e \'$!N;D\' file\nRun Code Online (Sandbox Code Playgroud)\n\n前两个表达式启动多行模式缓冲区,并允许其处理第一个匹配之前的前置上下文少于 3 行的边缘情况。中间(正则表达式匹配)表达式从窗口顶部打印一行,直到所需的匹配文本通过模式缓冲区向上传递。最后$!N;D一个将窗口滚动一行,除非到达输入末尾。