Linux 如何在打印前grep多个字符串并将其格式化

Linux 如何在打印前grep多个字符串并将其格式化,linux,awk,grep,Linux,Awk,Grep,我有一个txt文件,如下所示: cat file.txt <Some text here> <Some text here> Animal: type=Reptile age=17 s=M val=snake Animal Code: 123 Animal Color: Black Animal: type=Reptile age=20 s=M val=Lizard Animal Code: 200 Animal Color: light_Brow

我有一个txt文件,如下所示:

cat file.txt
<Some text here>
<Some text here>
Animal: type=Reptile age=17 s=M val=snake
   Animal Code: 123
   Animal Color: Black
Animal: type=Reptile age=20 s=M val=Lizard
   Animal Code: 200
   Animal Color: light_Brown
<Some text here>
<Some text here>
snake
123
Black
Lizard
200
light_Brown
其输出如下所示:

cat file.txt
<Some text here>
<Some text here>
Animal: type=Reptile age=17 s=M val=snake
   Animal Code: 123
   Animal Color: Black
Animal: type=Reptile age=20 s=M val=Lizard
   Animal Code: 200
   Animal Color: light_Brown
<Some text here>
<Some text here>
snake
123
Black
Lizard
200
light_Brown
我希望输出格式为代码、val、颜色,如下所示:

123,snake,Black
200,Lizard,light_Brown

如何实现这一点???

awk和grep在涉及多行时不是很强大-它们都最擅长一次处理一行。Awk可以从一行中记住一些东西并在另一行中使用,因此在您的特定情况下,只有Awk可以完成这项工作,但这需要一些工作

我假设行的顺序是固定的,所以在同一动物的“动物代码”之前不会有“动物颜色”行。另外,val=?被认为是“动物”系列的最后一件事

这个怎么样:

awk_prog='
/^Animal: type=Reptile/ { sub(".*val=",""); val=$0 }
/Animal Code: / { code=$NF }
/Animal Color: / { color=$NF ; print code "," val "," color }
'
awk "$awk_prog" file.txt

为了清晰起见,程序分为多行。当然,您可以将其全部放在一行。

这将允许您按自己喜欢的顺序打印任何字段,只需按其名称即可:

$ cat tst.awk
BEGIN { FS="[: =]+"; OFS="," }
/Animal/ {
    sub(/^ +/,"")
    for (i=2; i<NF; i+=2) {
        f[$i] = $(i+1)
    }
    if (/Color/) {
        print f["Code"], f["val"], f["Color"], f["age"], f["s"], f["type"]
        delete f
    }
}

$ awk -f tst.awk file
123,snake,Black,17,M,Reptile
200,Lizard,light_Brown,20,M,Reptile

根据需要进行按摩。

你的问题不是安全问题;你可能想问一下,这里的答案对你没有帮助吗?如果他们真的那么看看下一步该怎么做。你到底为什么会说awk和grep在涉及多行时不是很强大——他们都最擅长一次只处理一行。?这完全是胡说八道,因为awk是基于记录的,而不是像grep那样基于行的。@EdMorton:当然,如果你真的知道怎么做的话,awk可以做很多事情,但是它通常一次读取一行,并将给定的awk程序应用于每一行,一次一行。这是它最简单的操作模式,要以任何其他方式工作都需要付出努力。这就是为什么。也许这是我个人的观点——但我不会使用sed或awk来完成那些不是“一次一行”的任务,除非它是我唯一的工具。需要努力吗?将记录分隔符变量RS设置为任何分隔记录的变量,就完成了。您想用什么工具更容易处理多行记录?听起来你只是没有花太多时间和awk一起工作,可能是因为在某些时候被误传了。我在这里发表评论是为了确保其他人没有类似的错误信息。您只在一次一行操作中使用sed是正确的,就像grep一样,对于其他任何操作,您都应该使用awk。@EdMorton:我不怀疑有awk大师可以让它做任何事情,但是设置RS=a_非常长_字符串_等等,这不是它通常使用的方式。虽然我并不自称是专家,但在我的有生之年,我见过相当多的使用awk的脚本。很少有像我在这里写的例子或你自己的例子那样复杂,它们的大小和复杂度都差不多。如果我不得不做更多的事情——特别是文本文件中的多行记录,我通常会删除bash/awk/grep,然后用Python来完成。。。。。。cont我绝对不会向任何新人推荐RS=其他东西。像你和我这样的有经验的人,能够真正做到这一点,并且自信地阅读他们的剧本,他们很少来这里问问题——他们是来回答问题的。我正在根据提问者的水平调整我的建议——他们才刚刚开始学习。