【问题标题】:Extracting field from last row of given table using sed使用 sed 从给定表的最后一行中提取字段
【发布时间】:2013-04-18 10:32:30
【问题描述】:

我想编写一个 bash 脚本来提取表格最后一行中的字段。我将举例说明。我有一个文本文件,其中包含带有空格分隔字段的表格,例如 ...

Table 1 (foobar)
num  flag  name   comments
1    ON    Frank  this guy is frank
2    OFF   Sarah  she is tall
3    ON    Ahmed  who knows him

Table 2 (foobar)
num  flag  name   comments
1    ON    Mike   he is short
2    OFF   Ahmed  his name is listed twice

我想提取Table1最后一行的第一个字段,即3。理想情况下,我希望能够使用任何给定表格的标题来做到这一点。每个表之间有保证的回车。最好使用 sed 和 grep 来实现此目的的最佳方法是什么?

【问题讨论】:

  • 为什么要使用sedgrepawk做这种事的。
  • 主要用于学习目的,但也为了保持一致性。而且它也可以移植到不一定有 awk 的机器上。

标签: bash sed awk grep


【解决方案1】:

Awk 非常适合,打印每条记录最后一行的第一个字段:

$ awk '!$1{print a}{a=$1}END{print a}' file
3
2

仅从第一条记录开始:

$ awk '!$1{print a;exit}{a=$1}' file
3

编辑:

对于给定的表格标题:

$ awk -v t="Table 1" '$0~t{f=1}!$1&&f{print a;f=0}{a=$1}END{if (f) print a}' file
3

$ awk -v t="Table 2" '$0~t{f=1}!$1&&f{print a;f=0}{a=$1}END{if (f) print a}' file
2

【讨论】:

  • +1 确实,虽然 perfect 答案不会硬编码 3 列要求 :-) 不过还想不出优雅的方法!
  • @cbuckley 我会做$ awk '!$1{print a}{a=$1}END{print a}' file
  • @sudo_O 当我编辑我的问题描述时,你打败了我并发布了你的第二个答案。我只是提到字段的数量应该是动态的,因为这个 cmets 字段有空格。感谢您的出色回答!
  • 如果您不知道这是否是第一条记录,而您只是想摆脱表格的标题,您将如何回答变化?
【解决方案2】:

这条 sed 行似乎适用于您的示例。

table='Table 2'
sed -n "/$table"'/{n;n;:next;h;n;/^$/b last;$b last;b next;:last;g;s/^\s*\(\S*\).*/\1/p;}' file

解释:当我们在 $table 中找到与表名匹配的行时,我们跳过该行,然后跳过下一行(字段标签)。从 :next 开始,我们将当前行推入保持空间,获取下一行并查看它是否为空白或文件末尾,如果不是,我们返回 :next,将当前行推入保持并获取另一行。如果它是空白或 EOF,我们跳到 :last,将保持空间(表格的最后一行)拉入模式空间,将除第一个字段之外的所有字段都删除并打印。

【讨论】:

  • Wowwwww ...我想给这个一个 +2 以使用 sed 解决这个问题。在这个问题的情况下,我肯定明白为什么 awk 是首选方法。
  • 我是 sed 的忠实粉丝,但 awk 通常更适合这种事情。尽管如此,尝试让 sed 做到这一点还是很有趣的。
【解决方案3】:

只需将每个块读取为一条记录,每行作为一个字段,然后打印您关心的任何记录的最后一个字段的第一个子字段:

$ awk -v RS= -F'\n' '/^Table 1/{split($NF,a," "); print a[1]}' file
3

$ awk -v RS= -F'\n' '/^Table 2/{split($NF,a," "); print a[1]}' file
2

【讨论】:

    【解决方案4】:

    更好的工具是 awk!
    这是一个清晰易读的代码:

    awk '{
        if(NR==1) {
            row=$0;
            next;
        }
    
        if($0=="") {
            $0=row;
            print $1;
        } else {
            row=$0;
        }
    } END {
        if(row!="") {
            $0=row;
            print $1;
        }
    }' input.txt
    

    【讨论】:

    • 我同意。不过不是我。无论如何,谢谢你的回答。
    • 我也不是,但是 awk 社区是一群挑剔的人;似乎越简洁越好。 (编辑:找到the article I was looking for。)
    • 我同意爵士乐。人们经常在没有给出理由的情况下投反对票。
    • @user2150250 从问题中我不明白你想打印所有表格最后一行的第一个字段,不是吗?
    • @jyzuz 不,我只想从给定表标题的特定表中打印该字段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 2020-08-13
    • 2019-10-18
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多