Sed: 匹配后打印所有行

33

使用 sed 后,我得到了研究结果:

zcat file* | sed -e 's/.*text=\(.*\)status=[^/]*/\1/' | cut -f 1 - | grep "pattern"

但它只显示了我剪切的部分。如何打印匹配后的所有行?

我正在使用 zcat,所以无法使用 awk。

谢谢。

编辑:

这是我的日志文件:

[01/09/2015 00:00:47]       INFO=54646486432154646 from=steve   idfrom=55516654455457       to=jone       idto=5552045646464 guid=100021623456461451463   n
um=6    text=hi my number is 0 811 22 1/12   status=new      survstatus=new

我的目标是找到所有在我的网站上用他们的电话号码发送垃圾信息的用户(使用 grep "pattern"),然后打印所有行以获取关于每个垃圾邮件的所有信息。问题是可能会在INFO或id中发现匹配项,所以我先使用sed来获取文本。


你能展示一下 zcat 的样例输出以及你期望的输出吗? - anubhava
4
“我正在使用zcat,所以不能使用awk。”等等,什么? - JB.
你想要得到什么样的输出还不是很清楚。 - tripleee
你能否更明确地告诉我们你的日志文件是什么(例如,如果它只是你粘贴的单行,你不需要用sed处理,你也不必提供所有内容,但请给我们更多信息),以及你实际期望得到什么结果。用言语和例子说明。没有人能看懂你的想法。 - JB.
我认为JB的意思是zcat的输出只是标准文本,所以你可以毫不费力地将其管道传输到awk - abalter
6个回答

91
打印出第一个匹配项及其后的所有行:
$ echo -ne 'apple\nbanana\ncherry\n' | sed -ne '/banana/,$ p'
banana
cherry

打印第一个匹配项之后的所有行,但不包括第一个匹配项:
$ echo -ne 'apple\nbanana\ncherry\n' | sed -e '1,/banana/ d'
cherry

当模式在"text="和"status="之间匹配时,可以使用简单的grep进行行过滤,不需要使用sed和cut。
$ grep 'text=.*pattern.* status='

这个可以工作。不要忘记加上 -n,否则它会打印所有内容。 - Sandip Bhattacharya
这里的-e标志是做什么用的? - Caterina
@Caterina:它明确表明下一个参数是脚本本身。 - JB.
@Caterina 没必要的。 - Geremia

18

你可以使用awk

awk '/pattern/,EOF'

注意:不要被骗了,EOF只是未初始化的变量,默认为0(假)。因此,在文件末尾之前无法满足该条件。

也许这可以与之前所有使用awk的答案结合起来。


这对我来说非常完美,我之前不知道在awk中使用EOF! - AncientSwordRage
不要被骗了,EOF只是一个未初始化的变量,默认为0(false)。因此,除非到达文件结尾,否则无法满足该条件。 - karakfa
我已经编辑好了,希望没问题。 - AncientSwordRage

5
也许这正是你想要的?查找与“pattern”匹配的行,并提取text=后面的字段,直到status=之前。
zcat file* | sed -e '/pattern/s/.*text=\(.*\)status=[^/]*/\1/'

您没有透露pattern实际上是什么 - 如果它是一个变量,您不能在其周围使用单引号。
请注意,在您的示例中,\(.*\)status=[^/]*将匹配到survstatus=new。这可能不是您想要的?似乎没有任何地方有一个后面跟着斜杠的status= - 您真的应该更详细地解释一下您实际上想要做什么。
您的问题标题说“匹配后的所有行”,所以也许您想要text=之后的所有内容?那就简单了。
sed 's/.*text=//'

即将替换从text=开始的所有内容,并保留其余部分。(我相信您可以想出如何将周围的脚本更改为zcat file* | sed '/pattern/s/.*text=//'... 哎呀,也许我太天真了。)

实际上,您可能想要使用 ... | sed -n '/.../s/.../.../p' 仅打印提取的行。这也可以使用 Awk 轻松完成;不确定为什么您认为不能使用 Awk 完成此操作。 - tripleee

3
很少使用的branch命令可以帮你完成这个任务。在匹配之前,使用n进行下一个匹配,然后跳转到开头。匹配后,使用n跳过匹配行,然后循环复制剩余的行。
cat file | sed -n -e ':start; /pattern/b match;n; b start; :match n; :copy; p; n ; b copy'

5
记录一下,cat命令是无用的。 - tripleee
7
记录一下:关于“猫是无用的”评论是没有经过深思熟虑的。他或者我,可能在当前这一行之前只使用了两个命令行,比如“zcat FILE.gz | <复杂的sed命令>”,以及在那之前一个命令行是“gunzip FILE.gz”。有了历史记录和readline(命令行输入编辑工具),他和我现在可以按两次向上箭头键,按home键,删除一个字符(即“z”),然后按ENTER键来运行你所厌恶的命令。因此,“猫是无用的”评论通常比聪明更加愚蠢。 - user2849202

0
只需使用以下命令:grep -A$numberoflines "Word" file 如果你不知道numberoflines的数量,可以使用wc -l命令。

感谢您对Stack Overflow社区做出贡献的兴趣。这个问题已经有很多答案了,其中一个答案已经得到社区的广泛验证。您确定您的方法之前没有被提到过吗?如果是这样的话,能否请您解释一下您的方法有何不同,什么情况下您的方法可能更好,并且为什么您认为之前的答案不够满意。您能否请编辑您的答案并提供解释? - undefined

0
zcat file* | sed -e 's/.*text=\(.*\)status=[^/]*/\1/' | ***cut -f 1 - | grep "pattern"***

改为更改管道的最后两个段,使其如下:

zcat file* | sed -e 's/.*text=\(.*\)status=[^/]*/\1/' | **awk '$1 ~ "pattern" {print $0}'**

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接