代码之家  ›  专栏  ›  技术社区  ›  anish anil

sed/AWK/Cut…最佳选择是什么

  •  1
  • anish anil  · 技术社区  · 6 年前

    我的输出:

    docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    jenkins/jenkins     lts                 806f56c84444        8 days ago          703MB
    mongo               latest              0da05d84b1fe        2 weeks ago         394MB
    

    我想只从输出中剪切图像ID。

    我试过使用 cut :

    docker images | cut -d " " -f1
    REPOSITORY
    jenkins/jenkins
    

    这个 -f1 如果我使用 -f3 它往往是空的。由于分隔符不是单个空格,我不知道如何获得所需的输出。

    我们可以吗 基于字段名称?

    我阅读了文档,没有看到任何相关内容。我还发现,有一种方法可以使用sed/AWK实现这一点,我仍在研究中。

    同时,使用 命令

    我是Unix/Linux新手,如何确定我更喜欢哪个Sed/AWK/Cut?

    3 回复  |  直到 6 年前
        1
  •  2
  •   oguz ismail FCulig    6 年前

    您的输入似乎每个字段有20个字符的固定宽度,因此您可以使用gawk的 FIELDWIDTHS 特色

    $ awk -v FIELDWIDTHS="20 20 20 20 20" '{ print $3 }' file
    IMAGE ID
    806f56c84444
    0da05d84b1fe
    $
    $ awk -v FIELDWIDTHS="20 20 20 20 20" '{ printf "%20s%20s\n", $1, $3 }' file
    REPOSITORY          IMAGE ID
    jenkins/jenkins     806f56c84444
    mongo               0da05d84b1fe
    

    从…起 man gawk :

    如果FIELDWIDTHS变量设置为空格分隔的数字列表,则每个字段都应有固定的宽度,gawk使用指定的宽度拆分记录。每个字段宽度前面可以有一个冒号分隔的值,指定字段开始之前要跳过的字符数。忽略FS的值。将新值指定给FS或FPAT会覆盖FIELDWIDTHS的使用。

        2
  •  2
  •   TenG    6 年前

    您必须将默认输出中的空格填充“压缩”为单个空格。

    1 2 == 1-space-space-2 ==第一个空格前的字段1,第1和第2个空格之间的字段,第2个空格后的字段3。

    cut -d' ' -f1 ==>'1英尺

    cut -d' ' -f2 =“=>”第一个和第二个分隔符之间的空字段

    cut -d' ' -f3 ==>'2英尺

    所以,在你的情况下使用 sed 要将连续空格替换为1,请执行以下操作:

    docker images | sed 's/ */ /g' | cut -d " " -f1,3

    如果输出为固定列宽,则可以使用此剪切变量:

    docker images | cut -c1-20,41-60

    这将剪切第41列到第60列,在那里我们可以找到图像ID。

    如果输出使用 TAB 对于填充,你应该使用 expand -t n 要使输出一致地填充空格,请应用适当的 cut -cx,y ,例如(数字可能需要调整):

    docker images | expand -t 4 | cut -c1-20,41-60

        3
  •  1
  •   Darby_Crash    6 年前

    尝试以下操作:

    docker images | tr -s ' ' | cut -f3 -d' '
    

    命令 tr -s ' ' 将多个空格转换为一个空格,然后使用cut可以抓取字段。如果字段中的值没有空格,则此操作很好。

        4
  •  1
  •   tripleee    6 年前

    在一般情况下,避免分析用于人类消费的输出。许多现代实用程序提供了一个选项,可以以一些标准格式(如JSON或XML,甚至CSV)生成输出(尽管这没有那么严格的规定,并且存在多种“方言”)。

    docker 特别是有一个 --format option 允许您指定自己的输出格式:

    docker images --format "{{.ID}}"
    

    如果您无法避免编写自己的解析器(您真的确定吗?再看看!), cut 适用于使用特定单字符分隔符的输出,或其他相当常规的输出。对于其他一切,我都会选择Awk。开箱即用,它从 序列 空格,因此它正好满足您的具体要求:

    docker images | awk 'NR>1 { print $3 }'
    

    ( NR>1 跳过包含列标题的第一行。)

    对于固定宽度的列,它允许您按索引拉出字符串:

    docker images | awk 'NR>1 { print substr($0, 41, 12) }'
    

    。。。虽然你可以用 ,也是:

    docker images | cut -c41-53
    

    。。。但请注意,Docker可能会根据您的屏幕大小调整列宽!

    Awk还允许您编写正则表达式提取:

    awk 'NR>1 { sub(/^([^[:space:]]*[[:space:]]+){2}/, ""); sub(/[[:space]].*/, ""); print }'
    

    这就是它与 sed :

    sed -n '2,$s/^[^ ]\+[ ]\+[^ ]\+[ ]\+\([^ ]\+\)[ ].*/\1/p'
    

    虽然 sed公司 人类可读性明显降低,尤其是对于非平凡的脚本。(这仍然很琐碎。)

    如果您以前没有使用过regex,那么上面的内容看起来很神秘,但其实并不难区分。我们正在寻找非空格序列(列中的一个字段)后跟空格序列(列分隔符)——ID字段前面两个空格,后面是任何空格,从ID列后面的第一个空格开始。

    如果您想学习shell脚本,您可能还应该至少学习Awk的基础知识(以及对 sed公司 )。如果您只是想完成工作,可能对学习U*x工具不感兴趣(尽管您可能无论如何都应该如此!),或许可以学习Python或Ruby等现代脚本语言。

    。。。这里有一个 Python docker library :

    import docker
    client = docker.from_env()
    for image in client.images.list():
        print(image.id)
    
        5
  •  0
  •   I3ck    6 年前

    具有 Procedural Text Edit 它是:

    forEach line {
        if (contains ci "REPOSITORY") { remove }
        keepRange word 2 1
    }
    removeEmptyLines // <- optional
    
        6
  •  0
  •   James Brown    6 年前

    我们可以吗 cut 基于字段名称 ?不

    我如何确定要选择哪个Sed/AWK/Cut ?YMMV。对于字段由两个或多个空格分隔的特定输入,可以使用awk将字段分隔符设置为 " +" (两个或多个空格),查找所需的字段名( IMAGE ID 并仅打印该特定字段:

    $ awk -F"  +" '                     # set field separator
    {
        if(f=="")                       # while we have not determined the desired field
            for(i=1;i<=NF;i++)          # ... keep looking
                if($i=="IMAGE ID")
                    f=i
        if(f!="")                       # once found
            print $f                    # start printing it
    }' file
    

    输出:

    IMAGE ID
    806f56c84444
    0da05d84b1fe
    

    作为一个衬里:

    $ awk -F"  +" '{if(f=="")for(i=1;i<=NF;i++)if($i=="IMAGE ID")f=i;if(f!="")print $f}' file