【问题标题】:Convert a text file into columns将文本文件转换为列
【发布时间】:2019-01-15 23:59:44
【问题描述】:

假设我有科学数据,所有数字都排列在单列中,但表示 n(宽度)×m(高度)的强度矩阵。输入文件的列总共有 n * m 行。输入示例可能如下所示:

1  
2  
3  
......  
30 

新的输出应该是这样的,我有 n 个带有 m 行的新列。坚持我的例子,输入 30 个字段,n = 3,m = 10,我需要这样的输出文件(分隔符无关紧要,可以是空白,标签等):

1   11  21  
2   12  22  
... ... ...
10  20  30 

我在 Windows 下使用 gawk。请注意,没有特殊的FS,更多真实世界的例子是 60 * 60 或更大。

【问题讨论】:

    标签: linux unix awk


    【解决方案1】:

    如果您不仅限于awk,而是拥有 GNU core-utils(cygwin, native, ..),那么最简单的解决方案是使用pr

    pr -ts" " --columns 3 file
    

    【讨论】:

    • 非常感谢这个需要的解决方案,与 core-utils 完美搭配,但是如果输入的行数与 n*m 输出不匹配,awk 解决方案会更加灵活。不过,对一个新的有用命令感到满意。
    • 相同,但稍短:pr -3ts" " file
    【解决方案2】:

    我相信这样可以:

    awk '
      { split($0,data); }
      END {
         m = 10;
         n = 3;
         for( i = 1; i<=m; i++ ) {
            for( j = 0; j<n; j++ ) {
                printf "%s ", data[j*m + i] # output data plus space in one line
            }
            # here you might want to start a new line though you did not ask for it:
            printf "\n"; 
         }
      }' inputfile
    

    我的索引计数可能有误,但我相信您可以弄清楚。诀窍是第一行中的split。它将您的输入拆分为空格并创建一个数组dataEND 块在处理完您的文件后运行,并且仅通过索引访问 data。注意数组索引从 0 开始计数。

    假设所有数据都在一行中。你的问题在这方面不是很清楚。如果它位于多行上,则必须以不同的方式将其读入数组。

    希望这能让你开始。

    编辑 我注意到你在我回答的时候改变了你的问题。所以改变

    { split($0,data); }
    

    { data[++i] = $1; }
    

    考虑输入在不同的行。实际上,这可以让您首先将其读入二维数组。

    编辑 2

    读取二维数组 要读取为二维数组,假设 mn 事先已知且未以某种方式在输入中编码:

    awk '
      BEGIN {
         m = 10;
         n = 3;
      }
      { 
         for( i = 0; i<m; i++ ) {
            for( j = 0; j<n; j++ ) {
                data[i,j] = $0;
            }
         }
         # do something with data
      }' inputfile
    

    但是,由于您只想重新格式化数据,因此可以立即进行。结合这两种解决方案摆脱data并在命令行上传递mn

    awk -v m=10 -v n=3'
      { 
         for( i = 0; i<m; i++ ) {
            for( j = 0; j<n; j++ ) {
                printf "%s ", $0     # output data plus space in one line
            }
            printf "\n";
         }
      }' inputfile
    

    【讨论】:

    • 亲爱的迈克尔,非常感谢您的回答。它工作得很好,索引是正确的。抱歉回复晚了,复活节我不在。诀窍实际上是如何读取输入。您介意解释一下您的最后一句话如何读取 2dim 数组中的数据吗?事实上,数据只是在一个长的单列中(在第一个实例中格式错误)。非常感谢您的帮助。
    【解决方案3】:

    这是一个相当简单的解决方案(在示例中,我将 n 设置为 3;为 n 插入适当的值):

    awk -v n=3 '{ row = row $1 " "; if (NR % n == 0) { print row; row = "" } }' FILE
    

    这通过一次读取一行将每一行与前面的行连接起来来实现。当n 行被连接时,它会在一个新行上打印连接的结果。重复此过程,直到输入中没有更多行。

    【讨论】:

      【解决方案4】:

      你可以使用下面的命令

      paste - - - < input.txt
      

      默认情况下,分隔符是TAB,要更改分隔符,请使用以下命令

      paste - - - -d' ' < input.txt
      

      【讨论】:

        猜你喜欢
        • 2013-06-12
        • 2020-03-08
        • 2023-03-10
        • 2021-11-26
        • 2014-03-04
        • 2016-04-14
        • 2020-03-13
        相关资源
        最近更新 更多