流水线以获取某些数据

时间:2017-06-26 22:55:43

标签: 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

有很多这样的部分。对于这些部分,我只需要a : same部分以及bc字段的值。

示例输出:

#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语句中使用或使用条件的另一种方式?

4 个答案:

答案 0 :(得分:1)

也许awk可以帮到你;)试试这个:

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

输出:

red
one
blue
two

如果您还需要字段名称,只需将$2替换为$0中的print

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

输出:

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

顺便说一下,在运行awk版本20070501 macOS 10.12.4 上进行了测试。

答案 1 :(得分:0)

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       

答案 2 :(得分:0)

我发现当您在输入中有name-&gt;值对时,最好先创建一个表示该映射的数组,然后只需使用它们的名称即可得到字段值,例如:

$ 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

通过这种方式,只需调整脚本的最后两行,您就可以轻松而强大地修改脚本,以任何您想要的顺序打印您想要的任何字段。

答案 3 :(得分:0)

两个单行:

  1. 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
    
  2. 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
    

    工作原理:

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

    • 所以下一个周期, hold 缓冲区总是包含前一个    line, pattern 缓冲区包含当前行。

    • /^a : same$/为真时,运行大括号中的代码。它是x更改模式保留缓冲区,p rint中的内容 hold 缓冲区,(注释行),e x将其更改回来, p发送模式缓冲区,(搜索字符串),两次 得到n分机线和p rint,之后z aps pattern 缓冲区,(删除它)和p rint,(即。打印一个空行)。