【问题标题】:Linux script to transpose rows to columns将行转换为列的 Linux 脚本
【发布时间】:2018-10-01 20:47:35
【问题描述】:

我有以下数据集,需要稍微转置。我正在为脚本而苦苦挣扎。任何帮助,将不胜感激。所有列/值都是动态的

文件格式:

ID    FieldName          FieldValue

1   Rooms Required?        Yes

1   Country of Meeting     US

2   Rooms Required? 

2   Country of Meeting  

3   Rooms Required? Yes

3   Country of Meeting  US

4   Rooms Required? No

4   Country of Meeting  BL


需要输出:

ID  Rooms Required? Country of Meeting

1     Yes                   US

2       

3     Yes                   US

4     No                     BL

请帮忙

【问题讨论】:

  • 这不是真正的重复,它是根据 2 个不同的列对行进行排序
  • 什么是输出和输入字段分隔符?额外的空行是否也是输入/输出?字段可以有空值吗?
  • 您可以将任何管道作为输入分隔符。输出也为管道。第一列为 ID ,因此不能为空。第二列将具有列名,因此不能为空。第三列可以为空作为它的值。

标签: linux bash awk transpose


【解决方案1】:

一个纯粹的awk 解决方案,基于您的字段,由制表符'\t' 分隔,如下所示:

awk 'BEGIN { FS = "\t"; PROCINFO["sorted_in"] = "@ind_num_asc" } { if ( $1 !~ /^[0-9]+$/ ) next; A[$1][$2] = $3; H[$2] } END { printf "ID"; for (h in H) printf "\t" h; for (i in A) { printf "\n\n" i; for (j in A[i]) printf "\t" A[i][j] } print "\n" }' filename

并分解:

awk 'BEGIN {
    FS = "\t"  #Set Field Separator as the Tab
    PROCINFO["sorted_in"] = "@ind_num_asc"  #Set array order as numbers
}
{
    if ( $1 !~ /^[0-9]+$/ )  #Skip all rows without numeric ID
        next
    A[$1][$2] = $3  #Store value in multi-dimensional array
    H[$2]           #Store header name
}
END {
    printf "ID"
    for (h in H)    #Print all headers found
        printf "\t" h
    for (i in A) {  #Print each record with corresponding values
        printf "\n\n" i
        for (j in A[i])
            printf "\t" A[i][j]
    }
    print "\n"
}' filename

如果需要任何进一步的解释,请告诉我。这将适用于您以任意顺序设置的 的任意数量的字段。如果记录没有所有相同的字段,您的输出可能看起来参差不齐。

【讨论】:

  • 感谢您的回复。但是,它没有按预期工作。我得到如下数据。它没有显示所需房间的价值?需要身份证明室吗?会议国家 1 美国 3 美国
  • @Sunny,您必须对此进行扩展,我不确定您的结果有何不同。这一切都取决于您的字段由单个制表符 '\t' 字符分隔的假设。我做出这个假设是因为当我将您的代码粘贴到我的 IDE 中时,间距排列起来,就好像这些空格最初是制表符一样。
【解决方案2】:

以下是使用join(以及bash 用于shell)的一般思路:

$ echo ID Rooms Country; \
  join -j1 -o '0 1.4 2.5' -a1 -a2 -e- <(grep -F Rooms data.txt) <(grep -F Country data.txt)

ID Rooms Country
1 Yes US
2 - -
3 Yes US
4 No BL

根据您的需要调整它。

【讨论】:

  • 谢谢。但是我需要很好的列名。你也能解释一下Rooms data.txt和Country data.txt是什么
  • data.txt 是包含所有数据的文件,与您在问题中发布的相同。 “Rooms”和“Country”是该文件第 2 列中的单词。至于标题,只需添加一个echo 行(我会改变我的答案)
  • 您正在对列进行硬编码。我不想要那个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-20
  • 2016-09-09
相关资源
最近更新 更多