找到一些文本后如何阅读某些行?


12

找到一些文本后如何阅读一定数量的行?

例如。:

在以下位置找到“ Unix”后,请阅读下两行:

Test 1
Test 2
Test 3
Test 4
UNIX
Test 5
Test 6
Test 7
Test 8
Test 9

结果可以是:

Test 5
Test 6

注意:最后一个示例中的“ Unix”是一个参数,因此,它可以是任何其他文本。

我拥有的:

我仍然没有主意,只需要一点灯。考虑创建另一个脚本来做到这一点。

Answers:


10

一种awk解决方案:

$ awk '$0 == "UNIX" {i=1;next};i && i++ <= 2' file
Test 5
Test 6

说明

  • /^UNIX$/{i=1;next}:如果看到UNIX,则将变量设置i = 1为下一个输入。

  • 如果i设置了变量(意味着我们看到了UNIX),则i && i++ <= 2仅在之后的后两行中将其评估为真值UNIX,从而导致awk执行默认操作print $0

  • 在看到之前UNIXi未定义,并从之后的第三行开始UNIXi具有大于2的值,这使表达式i && i++ <= 2评估为false,导致awk什么也不做。


经过测试后,您解决方案即时消息,我收到此错误消息:1号线附近的错误systax紧急救助1号线

@冷:你跑了什么?请注意,$答案开头的符号是shell提示符,而不是awk命令的一部分。
cuonglm 2014年

另一个变体:awk '/^UNIX$/ {s=NR;next} s && NR<=s+2'
musiphil 2014年

我知道@cuonglm

@Cold:您的操作系统是什么?
cuonglm

12

一个grep解决方案:

grep -A2 -P '^UNIX$' file

说明: -A表示:在比赛后打印接下来的两行

要么 awk:

awk '$0=="UNIX"{getline; print; getline; print}' file

说明:该语句在($0=="UNIX")行中搜索UNIX 。如果给出了该值,它将获取下一个到其缓冲区(getline)并打印缓冲区(print)。这完成了两次。

或使用sed

sed -n '/^UNIX$/{n;p;n;p}' file

说明:该类适用于UNIX(/^UNIX$/)。如果找到,它将在中执行该部分{...}n表示下一个,p表示打印。这也完成了两次。


感谢@chaos,我将尝试您提供的最后2个选项。请附上每个选项的一些解释,我会理解并做的。
2014年

如果行数发生变化,我将对后两个选项进行多少次更改?谢谢
2014年

@冷看到我的编辑。要更改号码,如果线路重复getline; print;的部分awk语句或n;p;在部分sed语句。
2014年

感谢@chaos,但是增加的行数可以增加表达,并且我认为此更改不可行。你不觉得?如果100线?
2014年

@Cold然后,我将使用grep解决方案grep -A100 -P '^UNIX$' file | tail -n +2。尾部是除去第一留置权。在其他(sed,awk)中,您将不得不编写循环,这使其变得不那么简单。
2014年

4
grep -A 2 UNIX file.txt

grep的手册页描述了该选项,因此:

  -A NUM, --after-context=NUM
      Print NUM  lines  of  trailing  context  after  matching  lines.
      Places  a  line  containing  --  between  contiguous  groups  of
      matches.

嗨@Twinkles,好的回答,但是我的grep只有“ hblcnsviw”这个选项。但是逻辑很好。谢谢
2014年

这也将UNIX在输出中打印。
cuonglm 2014年

要省略UNIX,管它tail[...] | tail -n +1,或sed[...] | sed '1d'
DopeGhoti 2014年

1
@DopeGhoti:只有在输入文本中仅出现一次时,您tail和的sed '1d'建议才能正常工作UNIX。所有其他答案都允许多次出现。建议可能会更好... | grep -v UNIX。诚然,如果UNIX出现在第15和第17行上,这会变得很混乱
G-Man说'Resstate Monica'

好点。我非常确定,可以sed使用某种形式的来完成此操作sed '/UNIX/d;n;n;p/' /path/to/file,我只是将其保留下来并作为答案提交。
DopeGhoti 2014年

0

这似乎很好地解决了问题:

sed -n '/UNIX/{n;p;n;p}' /path/to/file

概念证明:

$ for i in {1..9}; do echo $i; done | sed -n '/4/{n;p;n;p}'
5
6

1
for循环周围的子外壳不是必需的。
暂停,直到另行通知。

确实不是;这是我今天早些时候在那个贝壳上的一些其他愚蠢的残余。括号被删除。
DopeGhoti 2014年

0

您可以使用ex

ex -s +'1,/UNIX/d|%p|q!' file_or_/dev/stdin

哪里:

  • 1,/UNIX/d- 匹配后删除文本
  • %p -打印缓冲区
  • q!-退出而不保存对文件的更改(用于wq就地编辑)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.