【问题标题】:rearrange columns using awk or cut command使用 awk 或 cut 命令重新排列列
【发布时间】:2013-07-29 04:05:13
【问题描述】:

我有 1000 列的大文件。我想重新排列,以便最后一列应该是第三列。为此我使用过,

cut -f1-2,1000,3- file > out.txt

但这不会改变顺序。

有人可以帮忙使用 cut 或 awk 吗?

另外,我想重新排列第 10 列和第 11 列,如下所示:

例子:

1   10   11   2   3   4   5   6   7   8   9   12  13  14  15  16  17  18  19  20

【问题讨论】:

  • 您是要在原始的第 2 列和第 3 列之间插入最后一列,使第 3 列变为第 4 列,还是要替换第 3 列?提供一些示例输入和预期输出(当然,使用 5 或 6 列,而不是 1000 列!)。
  • 是的,我试图在第二和第三之间插入而不是替换。

标签: awk cut


【解决方案1】:

试试这个 awk 单行:

awk '{$3=$NF OFS $3;$NF=""}7' file

这是将最后一列移至第三列。如果你有 1000 个,那么它会使用第 1000 个 col。

编辑

如果文件是制表符分隔的,你可以试试:

awk -F'\t' -v OFS="\t" '{$3=$NF OFS $3;$NF=""}7' file

EDIT2

添加示例:

kent$  seq 20|paste -s -d'\t'                              
1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19  20

kent$  seq 20|paste -s -d'\t'|awk -F'\t' -v OFS="\t" '{$3=$NF OFS $3;$NF=""}7'
1   2   20  3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19  

EDIT3

您没有给出任何输入示例。所以假设您在原始文件中没有空列。 (没有连续的多标签):

kent$  seq 20|paste -s -d'\t'|awk -F'\t'  -v OFS="\t" '{$3=$10 FS $11 FS $3;$10=$11="";gsub(/\t+/,"\t")}7'
1       2       10      11      3       4       5       6       7       8       9       12      13      14      15      16      17      18      19      20

毕竟我们可以循环打印这些字段。

【讨论】:

  • 谢谢。原始文件是制表符分隔的,并且使用此命令分隔符正在更改。应该怎么做才能保留制表符作为分隔符。
  • @user1779730 检查编辑
  • 谢谢。但它正在打印最后一列两次。即在第三列和最后一列。只需要一次
  • @user1779730 我看不到它发生。用一个例子检查我的 EDIT2。
  • @user1779730 我不明白你。我的命令在“EDIT2”中给出输出
【解决方案2】:

我认为你想要的是:

awk 'BEGIN{FS=OFS="\t"} {$3=$NF OFS $3; sub(OFS "[^" OFS "]*$","")}1' file

这也可能对您有用,具体取决于您的 awk 版本:

awk 'BEGIN{FS=OFS="\t"} {$3=$NF OFS $3; NF--}1' file

如果没有分号后面的部分,您的输出中将有尾随制表符。

【讨论】:

  • 我认为我们需要OFS var。因为没有OFS,当我们设置$3=xxx 并输出该行时,awk 将使用默认的OFS(空格)。它将更改原始文件格式。但OP没有给出示例输出。 ..顺便说一句,我喜欢NF-- 非常聪明。大师!
【解决方案3】:

由于很多人都在寻找这个,即使是最好的 awk 解决方案也不是很漂亮和易于使用,所以我想发布我用 Python 编写的解决方案 (mycut):

#!/usr/bin/env python3

import sys
from signal import signal, SIGPIPE, SIG_DFL
signal(SIGPIPE,SIG_DFL)

#example usage: cat file | mycut 3 2 1

columns = [int(x) for x in sys.argv[1:]]
delimiter = "\t"

for line in sys.stdin:
    parts = line.split(delimiter)

    print("\t".join([parts[col] for col in columns]))

我考虑添加 cut 的其他功能,例如更改分隔符和使用 * 打印剩余列的功能。但随后它将获得一个自己的页面。

【讨论】:

    【解决方案4】:

    awk' 的外壳包装函数,使用更简单的语法:

    # Usage: rearrange int_n [int_o int_p ... ] < file
    rearrange () 
    { 
        unset n;
        n="{ print ";
        while [ "$1" ]; do
            n="$n\$$1\" \" ";
            shift;
        done;
        n="$n }";
        awk "$n" | grep '\w'
    }
    

    例子...

    echo foo bar baz | rearrange 2 3 1
    bar baz foo 
    

    使用bash大括号展开,rearrange降序排列的前5项和后5项:

    echo {1..1000}a | tr '\n' ' ' | rearrange {1000..995} {5..1}
    1000a 999a 998a 997a 996a 995a 5a 4a 3a 2a 1a 
    

    /bin 中排序的 3 字母外壳:

    ls -lLSr /bin/?sh | rearrange 5 9 
    150792 /bin/csh 
    154072 /bin/ash 
    771552 /bin/zsh 
    1554072 /bin/ksh 
    

    【讨论】:

      猜你喜欢
      • 2011-01-08
      • 2011-04-26
      • 2012-11-27
      • 1970-01-01
      • 1970-01-01
      • 2012-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多