使用 shell 脚本将行按循环顺序转置为列

使用 shell 脚本将行按循环顺序转置为列

我想以循环顺序将行转置为列,并忽略第二次出现的列标题。

例如

我有以下数据

[ID] 10
[NAME] TOM
[AGE] 25

[ID] 11
[NAME] SAM
[AGE] 26

输出应该是这样的

[ID]|[NAME]|[AGE]
10|TOM|25
11|SAM|26

我尝试使用下面的 awk 命令

awk 'BWGIN { FS="]"; OFS="|";} {for (i=1; i<=NF; i++) a[i,NR]=$i
    max=(max<NF?NF:max)}
    END {for (i=1; i<=max; i++)
          {for (j=1; j<=NR; j++) 
              printf "%s%s", a[i,j], (j==NR?RS:FS)
          }
    }' source.txt

我得到以下结果

[ID][NAME][AGE][ID][NAME][AGE]
10]TOM]25]11]SAM]25

列名不断重复,Sam 数据应换行。

如何在不硬编码列名称并提取其相应值的情况下实现这一目标。我有超过 100 个专栏。感谢您为实现这一目标所提供的帮助。

答案1

磨坊主,从“xtab”转换为“csvlite”格式:

$ mlr --ixtab --ocsvlite --ofs '|' cat source.txt
[ID]|[NAME]|[AGE]
10|TOM|25
11|SAM|26

答案2

awk 'BEGIN{ OFS="|"; printhdr=1 }
  NF{
    hdr=(hdr=="" ? "" : hdr OFS) $1
    row=(row=="" ? "" : row OFS) $2
    next
  }
  printhdr{ print hdr; printhdr=0 }
  { print row; row="" }
  END{ print row }
' file

将标题字段和转置行附加到变量hdrrow 如果字段数不为零,则在找到没有字段的记录时打印变量。如果printhdr设置了标志,则标题仅打印一次,并且row变量也会打印在END块中以打印输入文件的最后转置行。

答案3

awk -v RS= -v OFS='|' '
    NR==1 { for (i=1; i<NF; i+=2) printf "%s%s", $i, (i<(NF-1) ? OFS : ORS) }
    { for (i=2; i<=NF; i+=2) printf "%s%s", $i, (i<NF ? OFS : ORS) }
' file
[ID]|[NAME]|[AGE]
10|TOM|25
11|SAM|26

相关内容