【问题标题】:Rearrange column with empty values using awk or sed使用 awk 或 sed 重新排列具有空值的列
【发布时间】:2015-08-19 05:42:06
【问题描述】:

我想重新排列 txt 文件的列,但是有空值,这会导致问题。例如:

测试文件:

Name    ID      Count   Date    Other
A       1       10      513     x
        6       15      312     x
        3       18      314     x
B       19      31      942     x
        8       29      722     x

当我尝试$ more testfile |awk '{print $2"\t"$1"\t"$3"\t"$4"\t"$5}' 它变成:

ID      Name    Count   Date    Other
1       A       10      513     x
15      6       312     x
18      3       314     x
19      B       31      942     x
29      8       722     x

这不是我想要的,请帮忙,我想要它

ID      Name    Count   Date    Other
1       A       10      513     x
15              6       312     x
18              3       314     x
19      B       31      942     x
29              8       722     x

另外我不确定哪些列可能包含空值,并且列长不固定,谢谢

【问题讨论】:

  • 输入文件是否已经被制表符分隔?试试awk -F'\t' ... 看看它能做什么。还要发布您想要的输出,而不仅仅是您不想要的输出。如果输入文件不是制表符分隔的,那么最好的解决方案是带有FIELDWIDTHS 的 GNU awk - 你有 GNU awk(awk --version 会告诉你)吗?
  • @EdMorton,是的,我的文件是制表符分隔的

标签: linux awk sed multiple-columns


【解决方案1】:

假设您的输入文件不是制表符分隔的,并且您拥有(或可以获得)GNU awk,那么我建议:

$ awk -v FIELDWIDTHS="8 8 8 8 8" -v OFS='\t' '{
    for (i=1;i<=NF;i++) {
        gsub(/^\s+|\s+$/,"",$i)
    }
    t=$1; $1=$2; $2=t'
}1' file
ID      Name    Count   Date    Other
1       A       10      513     x
6               15      312     x
3               18      314     x
19      B       31      942     x
8               29      722     x

如果您的文件是制表符分隔的,那么您只需要:

awk 'BEGIN{FS=OFS="\t"} {t=$1; $1=$2; $2=t}1' file

【讨论】:

  • 我的文件是制表符分隔的,您上面的评论就是答案!谢谢!!以下命令有效$ more file|awk -F'\t' '{print $2"\t"$1"\t"$3"\t"$4"\t"$5}' &gt; newfile
  • 也许你可以编辑这个答案,我可以检查它是否正确,谢谢!
  • 好的,我为制表符分隔的输入文件添加了正确的解决方案。
【解决方案2】:

另一种 awk 替代方法是使用字段数。如果你知道你的数据并且它只是第一列的不足,你可以试试这个。

awk -v OFS="\t" 'NF==4{$5=$4;$4=$3;$3=$2;$2=$1;$1=""} {print $2,$1,$3,$4,$5}'

但是,输出将以制表符分隔,而不是固定长度格式。您可以使用 printf 和更改 OFS 来实现相同的目的,但也许制表符分隔是您真正需要的表格表示形式。

【讨论】:

  • 这适用于小测试文件,但不适用于我的数据,不知道为什么
  • 使用awk '{print NF}' 测试您的数据以检查 awk 看到了多少字段。根据您的示例数据,它应该是 4 或 5。
【解决方案3】:

awk 使用的最自然的模型是由从空白到非空白再返回的转换定义的列。由于您的列本身可能是空白,因此自然模型将不起作用。

但是,您可以恢复使用基于列位置而不是转换的模型,这意味着文件仅包含空格(制表符的存在会使事情复杂化):

Name    ID      Count   Date    Other
A       1       10      513     x
        6       15      312     x
        3       18      314     x
B       19      31      942     x
        8       29      722     x

仍然可以重新排列,但不如基于转换的列简洁。

以下awk 脚本可以解决问题,交换nameid

{
    name  = substr($0, 1,7);
    id    = substr($0, 9,7);
    count = substr($0,17,7);
    date  = substr($0,25,7);
    other = substr($0,33  );
    print id" "name" "count" "date" "other;
}

如果原始文件名为 pax.in 并且 awk 脚本存储在 pax.awk 中,则命令 awk -f pax.awk pax.in 将根据需要为您提供:

ID      Name    Count   Date    Other
1       A       10      513     x
6               15      312     x
3               18      314     x
19      B       31      942     x
8               29      722     x

请记住,我编写的脚本相对灵活,允许您很容易地更改列的顺序。如果您只想交换前两列,则可以使用:

awk '{print substr($0,9,8)substr($0,1,8)substr($0,17)}' qq.in

或稍短一些(如果您被允许使用其他工具):

sed -E 's/^(.{8})(.{8})/\2\1/' qq.in

【讨论】:

  • 最后一个 awk 命令中 substr()s 之间的 ""s 没有任何用处。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-29
  • 1970-01-01
  • 2017-08-25
  • 2013-02-27
  • 1970-01-01
相关资源
最近更新 更多