【问题标题】:How do I turn a text file with a single column into a matrix?如何将具有单列的文本文件转换为矩阵?
【发布时间】:2017-10-26 08:56:13
【问题描述】:

我有一个包含单列数字的文本文件,如下所示:

1
2
3
4
5
6

我想把它转换成两列,按从左到右的顺序:

1 2
3 4
5 6

我可以做到:

awk '{print>"line-"NR%2}' file
paste line-0  line-1 >newfile

但我认为对两个中间文件的依赖会使其在脚本中变得脆弱。

我想使用cat file | mystery-zip-command >newfile之类的东西

【问题讨论】:

标签: linux bash unix text awk


【解决方案1】:

您可以使用paste 来执行此操作:

paste -d " " - - < file > newfile

你也可以使用pr:

pr -ats" " -2 file > newfile
  • -a - 使用循环顺序
  • -t - 禁止标头和尾标
  • -s " " - 使用单个空格作为分隔符
  • -2 - 两列输出

另见:

【讨论】:

  • 我想用'paste'接受答案,你能把它分开吗?
  • 只需将基于paste 的答案放在前面。
【解决方案2】:

另一种选择

$ seq 6 | xargs -n2

1 2
3 4
5 6

awk

$ seq 6 | awk '{ORS=NR%2?FS:RS}1'

1 2
3 4
5 6

如果您希望在输入行数为奇数的情况下以新行结束输出..

$ seq 7 | awk '{ORS=NR%2?FS:RS}1; END{ORS=NR%2?RS:FS; print ""}'

1 2
3 4
5 6
7

【讨论】:

    【解决方案3】:
    awk 'NR % 2 == 1 { printf("%s", $1) }
         NR % 2 == 0 { printf(" %s\n", $1) }
         END { if (NR % 2 == 1) print "" }' file
    

    奇数行打印后没有换行符,以打印第一列。偶数行首先打印一个空格,然后打印一个换行符,以打印第二列。最后,如果有奇数行,我们打印一个换行符,这样我们就不会在行的中间结束。

    【讨论】:

      【解决方案4】:

      使用 bash:

      while IFS= read -r odd; do IFS= read -r even; echo "$odd $even"; done < file
      

      输出:

      1 2 3 4 5 6

      【讨论】:

      • @EdMorton:我想出了一个 bash 解决方案,因为问题是用 bash 标记的,而 awk 已经有多个答案。 John 现在可以在非常不同的解决方案之间进行选择。好的,这个 bash 解决方案不是高性能的,也不是真正可扩展的。
      【解决方案5】:
      $ seq 6 | awk '{ORS=(NR%2?FS:RS); print} END{if (ORS==FS) printf RS}'
      1 2
      3 4
      5 6
      $
      $ seq 7 | awk '{ORS=(NR%2?FS:RS); print} END{if (ORS==FS) printf RS}'
      1 2
      3 4
      5 6
      7
      $
      

      请注意,它总是添加一个终止换行符 - 这很重要,因为未来的命令可能依赖于它,例如:

      $ seq 6 | awk '{ORS=(NR%2?FS:RS); print}' | wc -l
             3
      $ seq 7 | awk '{ORS=(NR%2?FS:RS); print}' | wc -l
             3
      $ seq 7 | awk '{ORS=(NR%2?FS:RS); print} END{if (ORS==FS) printf RS}' | wc -l
             4
      

      只需将2 的单次出现更改为3 或如果您的要求发生变化,您想要的任意多列:

      $ seq 6 | awk '{ORS=(NR%3?FS:RS); print} END{if (ORS==FS) printf RS}'
      1 2 3
      4 5 6
      $ seq 7 | awk '{ORS=(NR%3?FS:RS); print} END{if (ORS==FS) printf RS}'
      1 2 3
      4 5 6
      7
      $ seq 8 | awk '{ORS=(NR%3?FS:RS); print} END{if (ORS==FS) printf RS}'
      1 2 3
      4 5 6
      7 8
      $ seq 9 | awk '{ORS=(NR%3?FS:RS); print} END{if (ORS==FS) printf RS}'
      1 2 3
      4 5 6
      7 8 9
      $
      

      【讨论】:

        【解决方案6】:

        awk方法:

        awk '{print ( ((getline nl) > 0)? $0" "nl : $0 )}' file
        

        输出:

        1 2
        3 4
        5 6
        

        • (getline nl)&gt;0 - getline 将获取下一条记录并将其分配给变量 nlgetline 命令如果找到记录则返回1,如果遇到文件末尾则返回0

        GNU sed 方法:

        sed 'N;s/\n/ /' file
        
        • N - 向模式空间添加换行符,然后将下一行输入附加到模式空间

        • s/\n/ / - 在捕获的模式空间中用空格替换换行符

        【讨论】:

        • @EdMorton,不是两者兼而有之,sed 方法在序列1 2 3 4 5 6 7 上运行良好。至于 awk 方法 - 我已将其扩展为奇数序列
        【解决方案7】:
        seq 6 | tr '\n' ' ' | sed -r 's/([^ ]* [^ ]* )/\1\n/g'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-27
          • 2019-08-21
          • 1970-01-01
          • 1970-01-01
          • 2014-02-28
          • 1970-01-01
          相关资源
          最近更新 更多