使用 AWK 简单转换数据

使用 AWK 简单转换数据

我有一些这种格式的数据;-

Type,Fac1,Fac2,Fac3
1,0.1,0.1,0.1
2,0.2,0.2,0.2
3,0.3,0.3,0.3

使用 AWK,我需要转换数据,使其看起来像这样;-

Type
1,Fac1,0.1
1,Fac2,0.1
1,Fac3,0.1
2,Fac1,0.2
2,Fac2,0.2
2,Fac3,0.2
3,Fac1,0.3
3,Fac2,0.3
3,Fac3,0.3

换句话说,一种从水平方向转变为垂直方向的“枢转”动作。

所以我尝试了这个:

awk -F ',' '{for (i=2;i<=NF;i++) { if (i==2) {print $1"," $i } else print $1"," $i}}'

答案1

$ cat tst.awk
BEGIN { FS=OFS="," }
NR==1 {
    print $1
    split($0,tags)
    next
}
{
    for (i=2; i<=NF; i++) {
        print $1, tags[i], $i
    }
}

$ awk -f tst.awk file
Type
1,Fac1,0.1
1,Fac2,0.1
1,Fac3,0.1
2,Fac1,0.2
2,Fac2,0.2
2,Fac3,0.2
3,Fac1,0.3
3,Fac2,0.3
3,Fac3,0.3

答案2

perl逗号分隔线

perl -sF, -lane '
  $.==1 && do{
    print shift @F;
    @h = @F; next;
  };
  my $i;
  print $F[0], splice(@F,1,1), $h[$i++] while @F > 1;
' -- -,=, file

输出:-

Type
1,0.1,Fac1
1,0.1,Fac2
1,0.1,Fac3
2,0.2,Fac1
2,0.2,Fac2
2,0.2,Fac3
3,0.3,Fac1
3,0.3,Fac2
3,0.3,Fac3

将 Python 和列表理解与 itertools 模块结合使用

python3 -c 'import itertools as it, sys
ifile = sys.argv[1]
fs,rs = ",","\n"
ofs,ors = fs,rs
with open(ifile) as f:
  for nr,l in enumerate(f,1):
    L = l.rstrip(rs).split(fs)
    if nr == 1:
      print(L.pop(0))
      H = L
    else:
      print(*[ofs.join([a,*b])
      for a,b in zip(it.repeat(L.pop(0)),zip(L,H))],sep=ors)
' file

扩展正则表达式模式下的 GNU sed:-

sed -Ee '
  1{
    s/,/\n/;P
    s/.*\n//
    h;d
  }
  /\n/!G
  s/,/&\n/2
  s/^(([^,]*,).*)\n(.*\n)([^,]*),/\1\4\n\2\3/
  /\n.*\n/!s/\n/,/
  P;D
' file

相关内容