【问题标题】:Combine multiple columns of different lengths into one column in BASH在 BASH 中将不同长度的多列合并为一列
【发布时间】:2013-10-19 00:21:52
【问题描述】:

我需要使用 BASH 将不同长度的列组合成一列。这是一个示例输入文件:

11  1 2   3 4   5 6   7 8
12  1 2   3 4   5 6   7 8
13  1 2   3 4   5 6   7 8
14  1 2         5 6   7 8
15  1 2               7 8

还有我想要的输出:

1
1
1
1
1
3
3
3
5
5
5
5
7
7
7
7
7

输入数据是如图所示的列对。每对由固定数量的空格隔开。一对列中的值由一个空格分隔。提前致谢!

【问题讨论】:

    标签: bash shell awk


    【解决方案1】:

    使用 GNU awk 进行固定宽度字段处理:

    $ cat file
    1 2   3 4   5 6   7 8
    1 2   3 4   5 6   7 8
    1 2   3 4   5 6   7 8
    1 2         5 6   7 8
    1 2               7 8
    
    $ cat tst.awk                          
    BEGIN{ FIELDWIDTHS="1 1 1 3 1 1 1 3 1 1 1 3 1 1 1" }
    {
        for (i=1;i<=NF;i++) {
            a[NR,i] = $i
        }
    }
    END {
        for (i=1;i<=NF;i+=4)
            for (j=1;j<=NR;j++)
                if ( a[j,i] != " " ) 
                    print a[j,i]
    }
    
    $ gawk -f tst.awk file
    1
    1
    1
    1
    1
    3
    3
    3
    5
    5
    5
    5
    7
    7
    7
    7
    7
    

    【讨论】:

    • 谢谢!不幸的是,如果最后一列的行数比前一列多,则数字不会按需要打印出来。例如,this 输入文件将输出this。有什么修复吗?
    • 如何判断给定值在哪一列?列是固定宽度字段还是列对之间是否有选项卡或什么?更新您的问题以显示您在评论中链接的更有趣的输入/输出,并解释如何分辨数字所在的字段。
    • 我已经更新了这个问题。我不确定我是否理解您所说的“解释如何分辨数字在哪些字段中”的意思;你能详细说明一下吗?
    • 在你输入的最后一行 - 你怎么知道“7 8”在最后两列?是因为输入中有分隔数字对的制表符,还是因为 7 从该行的第 19 个字符开始或其他原因?输入中的每个空格都是一个空白字符吗?此外,更新您的输入和预期输出,以显示如果出现一些 2 位甚至 3 位数字时的样子。
    • 我在我的问题中发布了一些可能的示例输入。让我们知道这是否是有效的输入,如果不是,为什么不呢。然后更新您的问题以显示最坏情况的输入。
    【解决方案2】:

    您可以尝试以下方法:

    awk -f ext.awk input.txt
    

    input.txt 是您的输入数据文件,ext.awk 是:

    BEGIN {
        ncols=4 # number of columns
        nspc=3  # number of spaces that separates the columns
    }
    {
        str=$0;
        for (i=1; i<=ncols; i++) {
            pos=match(str,/^([0-9]+) ([0-9]+)/,a)
            if (pos>0) {
               b[NR,i]=a[1]
               if (NR==1) colw[i]=RLENGTH;  #assume col width are given as in first row
            }
            str=substr(str,colw[i]+1+nspc);
        }
    }
    END {
        for (i=1;i<=ncols;i++)
            for (j=1;j<=NR;j++) {
                if (b[j,i]) print b[j,i];
        }
    }
    

    【讨论】:

    • 这不能正常工作,因为分隔列的空格数在整个过程中并不相同。每对列之间用 3 个空格隔开,而一对中的数字用 1 个空格隔开。
    • 我不明白。你说列是用3个空格隔开的,但是你又说隔开列的空格个数不一样……
    • 如果你看一下我提供的示例输入,有成对的列。每对与另一对相隔 3 个空格。但是,在一对列中,列之间用 1 个空格分隔。
    • 代码似乎适用于您提供的示例。请提供代码不起作用的示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    • 2017-12-04
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多