仅当上行包含特定单词时才打印行

仅当上行包含特定单词时才打印行

我们有以下包含主机名和主机 IP 的文件(长文件,每台 Linux 机器有 90-100 台机器)

hosts.cluster.conf

  "href" : "http://localhost:8080/api/v1/hosts/worker02.sys87.com",
  "Hosts" : 
    "cluster_name" : "hdp",
    "host_name" : "worker02.sys87.com",
    "ip" : "23.67.32.65"


  "href" : "http://localhost:8080/api/v1/hosts/worker03.sys87.com",
  "Hosts" : 
    "cluster_name" : "hdp",
    "host_name" : "worker03.sys87.com",
    "ip" : "23.67.32.66"


  "href" : "http://localhost:8080/api/v1/hosts/worker04.sys87.com",
  "Hosts" : 
    "host_name" : "worker04.sys87.com",
    "ip" : "23.67.32.67"


  "href" : "http://localhost:8080/api/v1/hosts/worker05.sys87.com",
  "Hosts" : 
    "cluster_name" : "hdp",
    "host_name" : "worker05.sys87.com",
    "ip" : "23.67.32.68"

我们想打印所有主机名仅当上一行之前包含“集群名称“ 单词

预期成绩

"host_name" : "worker02.sys87.com",

"host_name" : "worker03.sys87.com",

"host_name" : "worker05.sys87.com",

答案1

sed '/host_name/!h;//!d;x;/cluster_name/!d;g' infile

host_name将保存与旧缓冲区不匹配的每一行h,然后d将其删除;对于每个剩余的行,它将x更改缓冲区,如果模式空间不包含cluster_name它将删除它,否则它将g从保留缓冲区和自动打印中返回原始行。

答案2

尝试

 awk '/cluster_name/ {p=1 ; next ;} 
 /host_name/ && p { print ; }
 {p=0}' 

这个基本上记住就行了cluster_name。如果host_name找到,cluster_name之前没有,则不会打印。

请注意,整个 awk 代码可以是一行。

答案3

短的awk解决方案:

awk '/cluster_name/{ cl=NR }/host_name/ && NR-1==cl' hosts.cluster.conf
  • /cluster_name/{ cl=NR }- 捕获记录"cluster_name"行数
  • /host_name/- 在相遇"host_name"线上
  • NR-1==cl- 确保当前"host_name"记录号NR"cluster_name"记录号之后的下一个(由 表示cl

输出:

"host_name" : "worker02.sys87.com",
"host_name" : "worker03.sys87.com",
"host_name" : "worker05.sys87.com",

如果host_name出现在第一行,尽管我对实际情况表示怀疑,请使用以下版本:

awk '/cluster_name/{ cl=NR }/host_name/ && cl && NR-1==cl' hosts.cluster.conf

答案4

好吧,我们已经有了sedawk现在是 GNU 的时候了grep

cat infile | grep --after-context 1 cluster_name | grep host_name

解释

第一个命令cat将数据读出到管道中进行处理。您可以将此段替换为将源文本输出到 的任何命令stdout

第二个命令查找其中包含“cluster_name”的任何行,并打印它和下一行。中间输出是这样的:

"cluster_name" : "hdp",
"host_name" : "worker02.sys87.com",
--
"cluster_name" : "hdp",
"host_name" : "worker03.sys87.com",
--
"cluster_name" : "hdp",
"host_name" : "worker05.sys87.com",

然后最后一段仅打印其中包含“host_name”的行的内容。因此最终的输出是:

"host_name" : "worker02.sys87.com",
"host_name" : "worker03.sys87.com",
"host_name" : "worker05.sys87.com",

评论

  1. 并不是每个人grep都有“--before-context parameter.确保您使用的是 GNU grep”,并且应该没问题。
  2. 如果这是像 JSON 这样的语言,那么您最好学习和使用适合语言的解析器,例如 jmespath 或jq.

相关内容