我想以循环顺序将行转置为列,并忽略第二次出现的列标题。
例如
我有以下数据
[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
将标题字段和转置行附加到变量hdr
,row
如果字段数不为零,则在找到没有字段的记录时打印变量。如果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