【问题标题】:How to get second last field from a cut command如何从剪切命令中获取倒数第二个字段
【发布时间】:2013-07-12 17:06:48
【问题描述】:

我有一组数据作为输入,需要基于分隔符的倒数第二个字段。这些行可能有不同数量的分隔符。我怎样才能获得倒数第二场?

示例输入

text,blah,blaah,foo
this,is,another,text,line

预期输出

blaah
text

【问题讨论】:

    标签: unix awk cut


    【解决方案1】:

    Unix cut except last two tokens 得到提示并能够找出答案:

    cat datafile | rev | cut -d '/' -f 2 | rev
    

    【讨论】:

    • +1 表示不使用 awk,但仍然简洁......虽然我大部分时间也使用 awk:P
    • rev 实际上可以将文件作为参数,所以这是 UUoC 案例
    • 保持线性顺序不是也永远不会是“UUoC”。 @SergiyKolodyaznyy
    • @JanKyuPeblik 请解释一下。 cat 和拥有两个通过管道进行额外缓冲的进程有什么好处,而不是只有一个 rev 进程可以达到与两个相同的结果?
    • @JanKyuPeblik 抱歉,但仍不清楚。 “保持线性顺序”在这里似乎没有必要,特别是因为答案表明他们实际上是先反转线路以进行处理并再次反转。 cat datafile | rev 没有明显优于 rev datafile
    【解决方案2】:

    Awk 非常适合:

    awk -F, '{print $(NF-1)}' file
    

    变量 NF 是一个特殊的 awk 变量,它包含当前记录中的字段数。

    【讨论】:

    • +1。我个人更喜欢纯 bash,但 awk 比大管道方法要好得多。
    【解决方案3】:

    这里根本不需要使用cutrev 或任何其他bash 外部工具。只需将每一行读入一个数组,然后选择你想要的部分:

    while IFS=, read -r -a entries; do
      printf '%s\n' "${entries[${#entries[@]} - 2]}"
    done <file
    

    在纯 bash 中执行此操作比启动管道要快得多,至少对于相当小的输入是这样。对于较大的输入,更好的工具是 awk。

    【讨论】:

    • 我不会说没有理由.. 对于一个简单的任务来说,这是很多讨厌的语法,我个人会多花几纳秒。无论如何,+1 用于提供强大的 bash 解决方案。
    • 说当你可以使用 bash 结构时没有理由使用外部工具就像说当你可以使用剪刀时没有理由使用割草机一样。 shell 只是一个环境,从中可以调用工具和操作文件和进程以及一些结构来对所有这些进行排序。与任何其他形式的构建一样,在构建软件时,只需为每项工作使用正确的工具。
    • @EdMorton 这可能是一个不错的插曲,但它实际上并不符合现在的世界。 bash 是一个相当完整的编程环境,并提供了在进程中执行大多数常见操作所需的工具。你不会编写 Python 代码来调用 Python 内置的操作的外部工具;为什么要在 bash 中这样做?
    • @EdMorton ...再深入一点:这不是你爷爷的 Bourne shell。 bash 具有适当的数组(C 字符串)、映射/散列数据类型、间接变量引用。 40 年前,shell 可能只是一种工具,除了设置管道什么都不做,但现在不是。
    • 然后解释一下 - 对于在 awk 中需要眨眼处理的输入,您可以使用 bash 在稍短的眨眼间完成,然后准备好随着数据的增长,性能受到严重影响。因此,bash 解决方案比 awk 编写起来更麻烦,并且在性能实际上是您关心的事情(即在大型数据集上)的情况下,它的运行速度比 awk 慢得多。那么,我可以说,没有理由用 bash 编写它,而只是作为一个学术练习,只是为了向人们展示如何使用 bash 结构。
    【解决方案4】:

    这个问题最简单的答案是使用我的cuts 实用程序:

    $ cat file.txt
    text,blah,blaah,foo
    this,is,another,text,line
    
    $ cuts -2 file.txt
    blaah
    text
    

    cuts,代表“类固醇切割”:

    - automatically figures out the input field separators
    - supports multi-char (and regexp) separators
    - automatically pastes (side-by-side) multiple columns from multiple files
    - supports negative offsets (from end of line)
    - has good defaults to save typing + allows the user to override them
    

    还有更多。

    在对 Unix 上的 cut 的太多限制感到沮丧之后,我写了 cuts。它旨在替换各种cut/paste 组合,从多个文件中切片和切块列,具有多种分隔符变体,同时尽量减少用户输入。

    你可以从github获取cuts(免费软件,Artistic License):https://github.com/arielf/cuts/

    不带参数调用cuts 将打印详细的Usage 消息。

    【讨论】:

    • 您好,感谢您分享您的脚本!也许“极简主义”并不是描述它的最佳方式,因为需要安装一个 perl 脚本,但拥有像这样包含 UNIX 哲学的智能东西绝对是有用的。我要把它藏在我的实用程序中......
    【解决方案5】:

    Perl 解决方案类似于来自@iiSeymour 的 awk 解决方案

    perl -lane 'print $F[-2]' file
    

    使用这些命令行选项:

    • n循环输入文件的每一行,不要自动打印每一行

    • l 在处理之前删除换行符,然后将它们添加回

    • a 自动拆分模式 – 将输入行拆分到 @F 数组中。默认为空格分割

    • e执行perl代码

    @F 自动拆分数组从索引 [0] 开始,而 awk 字段以 $1 开始
    -1 是最后一个元素
    -2 是倒数第二个元素

    【讨论】:

      【解决方案6】:

      GNU 代码

      $ echo text,blah,blaah,foo|sed -r 's/^(\S+,){2}(\S+),.*/\2/' 废话 $ echo this,is,another,text,line|sed -r 's/^(\S+,){2}(\S+),.*/\2/' 文本

      类似sudo_O的awkcode的代码示例:

      $ sed -r 's/.*,(\w+),\w+$/\1/' 文件 废话 文本

      CSV 文件使用更专业的程序可能会更好,例如。

      【讨论】:

      • 这没有得到倒数第二个字段,并且它仅限于每行固定数量的字段。我不会为此使用正则表达式。
      猜你喜欢
      • 2021-02-07
      • 2017-11-11
      • 2019-12-04
      • 1970-01-01
      • 2015-03-19
      • 2022-08-09
      • 2012-06-18
      • 2021-07-31
      • 1970-01-01
      相关资源
      最近更新 更多