找到一个模式和打印线基于找到第一个模式sed,awk grep

时间:2016-02-24 21:27:06

标签: linux bash awk sed grep

我有一个相当大的文件。所有共同点是打破每个部分示例的主机名:

HOSTNAME:host1
   data 1
     data here
   data 2 
      text here
   section 1
      text here
   part 4  
      data here
   comm = 2

HOSTNAME:host-2

   data 1
     data here
   data 2 
      text here
   section 1
      text here
   part 4  
      data here
   comm = 1

以上打印

如您所见,在每个部分之间还有其他部分按关键字或具有特定值的行分解

我喜欢使用oneliner为每个部分打印主机名,然后在每个主机名部分下打印我想要提取的行

你能帮忙吗?我现在正在使用grep -C 10 HOSTNAME | gerp -C模式 但这假定每个部分有10行。这不是最佳方法;有人可以表现出更好的方式。我还需要能够在我找到的每个模式下打印多行。因此,如果我找到data1并且其下有其他行,我喜欢抓取并打印它们

所以命令的输出就像

grep -C 10 HOSTNAME | grep data 1  
grep -C 10 HOSTNAME | grep -A 2 data 1 

HOSTNAME:Host1

   data 1  

HOSTNAME:Hoss2

   data 1 

除了Grep我使用这个sed命令打印我的输出

sed -r '/HOSTNAME|shared/!d' filename

这个sed命令的唯一问题是它只打印具有共享模式的行。其中有HOSTNAME。我还需要在匹配模式共享的行下指定我喜欢打印的行数。所以我喜欢打印HOSTNAME并在第二个共享搜索模式下给出我想要打印的行数。

谢谢

4 个答案:

答案 0 :(得分:0)

这是一个sed twoliner:

sed -n -r '/HOSTNAME/ { p }                                  
          /^\s+data 1/ {p }' hostnames.txt 

打印(p

  • 当该行包含HOSTNAME
  • 当行以一些空格(\s+)开头,后跟您的搜索条件(data 1
  • 未打印非mathing行(由于sed -n选项)

编辑:一些评论:

  • 这是在linux
  • 下用GNU sed 4.2.2测试的
  • 如果您的sed版本不支持,则不需要-r,请将第二种模式替换为/^.*data 1/
  • 我们可以使用;
  • 将所有内容压缩到一行

总而言之,这是一行中的修订版本,不需要扩展的正则表达式(即没有-r):

sed -n '/HOSTNAME/ { p } ; /^.*data 1/ {p }' hostnames.txt

答案 1 :(得分:0)

awk救援!

$ awk -v lines=2 '/HOSTNAME/{c=lines} NF&&c&&c--' file

HOSTNAME:host1
   data 1
HOSTNAME:host-2
   data 1

打印lines行数,包括模式匹配,跳过空行。

如果要指定辅助关键字而不是行数

$ awk -v key='data 1' '/HOSTNAME/{h=1; print} h&&$0~key{print; h=0}' file

HOSTNAME:host1
   data 1
HOSTNAME:host-2
   data 1

答案 2 :(得分:0)

OP要求似乎非常不清楚,但以下内容与对所要求的内容的一种解释是一致的,更重要的是,该程序没有特殊要求,并且可以轻松修改代码以满足各种要求。特别是,两种搜索模式(HOSTNAME模式和"数据1"模式)都可以轻松参数化。

主要思想是打印指定子部分中的所有行,或至少某个限制的某个数字。

如果应打印子部分中的行数限制,请指定限制值,否则将其设置为0.

awk -v limit=0 '
  /^HOSTNAME:/ { subheader=0; hostname=1; print; next}
  /^ *data 1/  { subheader=1; print; next }
  /^ *data /   { subheader=0; next }          
  subheader && (limit==0 || (subheader++ < limit)) { print }'

根据问题中提供的行,输出将为:

HOSTNAME:host1
   data 1
HOSTNAME:host-2
   data 1

(是的,我知道awk程序中的变量&#39;主机名&#39;目前尚未使用,但我将其包含在内以便于添加测试以满足关于识别子标题的前提条件的某些明显要求。)

答案 3 :(得分:0)

sed -n -e&#39; / hostname /,+ p&#39; -e&#39; / Duplex /,+ p&#39; 最简单的方法是组合两个sed命令..