Bash 获取特定数据的流水线

Bash 获取特定数据的流水线,bash,shell,awk,pipelining,Bash,Shell,Awk,Pipelining,我有一个命令,它给出以下输出: #sec one a : same b : red c : one d : e : f : #sec two a : same b : blue c : two d : e : #sec three a : different b : green c : three d : e : #sec four a : different b : yellow c : four #sec five a : different b : pink c : five 有

我有一个命令,它给出以下输出:

#sec one
a : same
b : red
c : one
d :
e :
f :

#sec two
a : same
b : blue
c : two
d :
e :

#sec three
a : different
b : green
c : three
d :
e :

#sec four
a : different
b : yellow
c : four

#sec five
a : different
b : pink
c : five
有很多这样的章节。我只需要具有
a:same
以及这些部分的
b
c
字段值的部分

样本输出:

#sec one
a : same
b : red
c : one


#sec two
a : same
b : blue
c : two
这就是我到目前为止所做的! Tr-s使其等间距

mycommand | tr -s " " | cut -d ':' -f 2

有人知道另一种方法吗,或者在cut语句中使用条件句吗?

也许
awk
可以在这里帮助您;)试试这个:

mycommand | tr -d " " | awk -F: '/a:/ {a=$2;} /(b:|c:)/ {if (a == "same") print $2;}'
输出:

red
one
blue
two
b:red
c:one
b:blue
c:two
如果您还需要字段名,只需在最后一次打印时将
$2
替换为
$0

mycommand | tr -d " " | awk -F: '/a:/ {a=$2;} /(b:|c:)/ {if (a == "same") print $0;}'
输出:

red
one
blue
two
b:red
c:one
b:blue
c:two

顺便说一下,在运行
awk
version
20070501
的macOS 10.12.4上进行了测试

awk
救援

$ awk -v RS= -F'\n' '/a : same/{print $1; 
                                for(i=2;i<=NF;i++) if($i~/^(a|b|c)/) print $i; 
                                print ""}' file    

#sec one                                                                                                                                  
a : same                                                                                                                                  
b : red                                                                                                                                   
c : one                                                                                                                                   

#sec two                                                                                                                                  
a : same                                                                                                                                  
b : blue                                                                                                                                  
c : two       
$awk-vrs=-F'\n'/a:same/{print$1;

对于(i=2;i我发现,当您的输入中有名称->值对时,最好先创建一个表示该映射的数组,然后只需使用字段名称即可获取字段值,例如:

$ cat tst.awk
BEGIN { RS=""; ORS="\n\n"; FS=OFS="\n" }
{
    delete n2v
    for (i=2;i<=NF;i++) {
        name = value = $i
        sub(/[[:space:]]*:.*/,"",name)
        sub(/^[^:]+:[[:space:]]*/,"",value)
        n2v[name] = value
    }
}
n2v["a"] == "same" { print $1, p("a"), p("b"), p("c") }
function p(n) { return (n " : " n2v[n]) }

$ awk -f tst.awk file
#sec one
a : same
b : red
c : one

#sec two
a : same
b : blue
c : two
$cat tst.awk
开始{RS=”“;ORS=“\n\n”;FS=OFS=“\n”}
{
删除n2v
对于(i=2;i2个一行程序:

  • GNU
    grep
    方法:

    grep --group-separator= -B1 -A2 '^a : same$' input_file
    
    输出:

    #sec one
    a : same
    b : red
    c : one
    
    #sec two
    a : same
    b : blue
    c : two
    
    #sec one
    a : same
    b : red
    c : one
    
    #sec two
    a : same
    b : blue
    c : two
    
  • 使用
    sed
    进行一点缓冲:

    sed -n '/^a : same$/{x;p;x;p;n;p;n;p;z;p};h' input_file
    
    输出:

    #sec one
    a : same
    b : red
    c : one
    
    #sec two
    a : same
    b : blue
    c : two
    
    #sec one
    a : same
    b : red
    c : one
    
    #sec two
    a : same
    b : blue
    c : two
    

    工作原理:

    • /^a:same$/
      找到要打印的部分,但它从来不是第一个 行(前面总是有注释行),所以第一个代码 执行的是
      h
      ,它覆盖了“hold”中的任何内容 与当前行的缓冲区

    • 因此,在下一个循环中,保持缓冲区始终包含上一个循环 行,模式缓冲区包含当前行

    • /^a:same$/
      为真时,将运行大括号中的代码。它将更改模式并保留缓冲区,
      p
      打印中的内容
      保留缓冲区(即注释行)e
      x
      将其更改回,
      p
      将模式缓冲区(即搜索字符串)打印两倍 获取
      n
      ext行并
      p
      rint它,然后它
      z
      aps 模式缓冲区(将其删除),并打印(即打印一个空行)

  • 我建议用Bash以外的语言进行这种结构化解析。这可能是可行的,但会很痛苦。如果你以前从未使用过Python,那么试试Python,这将是一个有趣的练习。不能同时使用awk吗?是的,使用awk绝对不重要。你想打印b和c部分,因为它们是以字母开头的吗s b和c,还是因为它们在
    右侧非空?