在动态更改文件中有效地转换bash中tab / new行分隔文件的输出

时间:2016-10-28 15:22:39

标签: linux bash awk sed

修改 行数和制表符分隔值也是动态的,因为它可以更改。所以它可能是1-5或1-10,具有相同的布局,但该区域将只列出一次。

我的文件格式如下:(@ TSV)

host1   host2   host3
id1 id2 id3
ip1 ip2 ip3
name1   name2   name3
role1   role2   role3
region

我也可以格式化文件:

host1
host2
host3
id1
id2
id3
ip1
ip2
ip3
name1
name2
name3
role1
role2
role3
region

我想写一个新文件或内联修改此文件,因此文件采用以下格式:(tsv)

host1   id1 ip1 name1 role1 region
host2   id2 ip2 name2 role2 region
host3   id3 ip3 name3 role3 region

我尝试过使用awk,sed,for循环没有成功......我需要一些新的想法。

3 个答案:

答案 0 :(得分:0)

您可以使用以下awk脚本:

# translate.awk

NR==1 {
    split($0,hosts)
}
NR==2 {
    split($0,ids)
}
NR==3{
    split($0,ips)
}
NR==4{
    split($0,names)
}
NR==5{
    split($0,roles)
}
NR==6{
    region=$1
}

END{
    OFS="\t"
    for(i in hosts) {
        print hosts[i], ids[i], ips[i], names[i], roles[i], region
    }
}

这样称呼:

awk -f translate.awk input.file

答案 1 :(得分:0)

从列表格式化版本开始,如果您没有丢失数据,即" religion" 3次,这会容易得多。

您可以动态添加缺失的值,然后只需添加pr

$ awk '1; END{print;print}' file | pr -6ts

host1   id1     ip1     name1   role1   region
host2   id2     ip2     name2   role2   region
host3   id3     ip3     name3   role3   region

如果列数已知且只有最后一个值可能丢失,则可以按列数进行参数化

$ cols=6; awk -v cols=$cols '1; END{for(i=1;i<=(NR-cols)/(cols-1);i++) print}' file |
  pr -${cols}ts

答案 2 :(得分:0)

将行转换为列的惯用awk方法:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
{
    numCols = NR
    numRows = (NF>numRows ? NF : numRows)
    for (rowNr=1; rowNr<=NF; rowNr++) {
        vals[rowNr,numCols] = $rowNr
    }
}
END {
    for (rowNr=1; rowNr<=numRows; rowNr++) {
        for (colNr=1; colNr<=numCols; colNr++) {
            val = ((rowNr,colNr) in vals ? vals[rowNr,colNr] : vals[1,colNr])
            printf "%s%s", val, (colNr<numCols ? OFS : ORS)
        }
    }
}

$ awk -f tst.awk file
host1   id1     ip1     name1   role1   region
host2   id2     ip2     name2   role2   region
host3   id3     ip3     name3   role3   region

以上是在您的第一个输入文件上运行的:

$ cat file
host1   host2   host3
id1     id2     id3
ip1     ip2     ip3
name1   name2   name3
role1   role2   role3
region

请注意,脚本不会引用输入中的任何值,也不会引用您有多少行或列,也不会引用任何其他有关输入文件内容的假设,除非缺少值,您希望重复第一个。