使用 awk 或 sed 重新排列具有空值的列

Rearrange column with empty values using awk or sed

我想重新排列 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 "\t""\t""\t""\t"}' 它变成:

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 使用的最自然的模型是从白色-space 到非白色-space 并返回的过渡所定义的列。由于您的列本身可能是白色的-space,自然模型将不起作用。

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

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([=11=], 1,7);
    id    = substr([=11=], 9,7);
    count = substr([=11=],17,7);
    date  = substr([=11=],25,7);
    other = substr([=11=],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([=13=],9,8)substr([=13=],1,8)substr([=13=],17)}' qq.in

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

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

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

$ awk -v FIELDWIDTHS="8 8 8 8 8" -v OFS='\t' '{
    for (i=1;i<=NF;i++) {
        gsub(/^\s+|\s+$/,"",$i)
    }
    t=; =; =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=; =; =t}1' file

awk 的另一种选择是使用字段数。如果你知道你的数据并且它只是第一列中的赤字,你可以试试这个。

awk -v OFS="\t" 'NF==4{=;=;=;=;=""} {print ,,,,}'

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