Bash 使用awk脚本转换csv文件

Bash 使用awk脚本转换csv文件,bash,awk,Bash,Awk,我有如下csv文件: C1, C2, C3,Cv1,Cv2,Cv3,Cv4 ... this one can be have longer column x1, x2 ,x3.1, 1.1, 1.2, 1.3, 1.4 x1, x2, x3.2, 2.1, 2.2, 2.3, 2.4 x1, x2, x3.3, 3.1, 3.2, 3.3, 3.4 C1,C2, C3,CTEXT,XVALUE x1, x2, x3.1, Cv1 , 1.1 x1, x2, x3.1, Cv2 , 1

我有如下csv文件:

C1, C2,   C3,Cv1,Cv2,Cv3,Cv4 ...  this one can be have longer column
x1, x2 ,x3.1, 1.1, 1.2, 1.3, 1.4
x1, x2, x3.2, 2.1, 2.2, 2.3, 2.4
x1, x2, x3.3, 3.1, 3.2, 3.3, 3.4
C1,C2,   C3,CTEXT,XVALUE
x1, x2, x3.1, Cv1 , 1.1
x1, x2, x3.1, Cv2 , 1.2
x1, x2, x3.1, Cv3 , 1.3
x1, x2, x3.1, Cv4 , 1.4
x1, x2, x3.2, Cv1 , 2.1
x1, x2, x3.2, Cv2 , 2.2
x1, x2, x3.2, Cv3 , 2.3
x1, x2, x3.2, Cv4 , 2.4
x1, x2, x3.3, Cv1 , 3.1
x1,x2,x3.3, Cv2 , 3.2
x1,x2,x3.3, Cv3 , 3.3
x1,x2,x3.3, Cv4 , 3.4
我想将此csv文件转换为以下格式:

C1, C2,   C3,Cv1,Cv2,Cv3,Cv4 ...  this one can be have longer column
x1, x2 ,x3.1, 1.1, 1.2, 1.3, 1.4
x1, x2, x3.2, 2.1, 2.2, 2.3, 2.4
x1, x2, x3.3, 3.1, 3.2, 3.3, 3.4
C1,C2,   C3,CTEXT,XVALUE
x1, x2, x3.1, Cv1 , 1.1
x1, x2, x3.1, Cv2 , 1.2
x1, x2, x3.1, Cv3 , 1.3
x1, x2, x3.1, Cv4 , 1.4
x1, x2, x3.2, Cv1 , 2.1
x1, x2, x3.2, Cv2 , 2.2
x1, x2, x3.2, Cv3 , 2.3
x1, x2, x3.2, Cv4 , 2.4
x1, x2, x3.3, Cv1 , 3.1
x1,x2,x3.3, Cv2 , 3.2
x1,x2,x3.3, Cv3 , 3.3
x1,x2,x3.3, Cv4 , 3.4
下面是我的代码:

#!/bin/bash
awk -F, -v OFS=, '{ if (NR==1)
{ print $1,$2,$3, "CTEXT","XVALUE"
  i=4; while (i < NF) {
   a[i]=$i; i=i+1
  }
  am=NF; next
}
i=4 ; while (i < am) {
  if (i > NF) {print "record "NR" insufficient value" >/dev/stderr
  break}
  print $1,$2,$3,a[i],$i
  i=i+1
  }
if (am <NF) print "record "NR" too many values for text" >/dev/stderr
}' input.csv

即使您将Solaris awk切换为gawk或nawk,仍然存在 还有一些问题。请您尝试以下方法:

awk -F, -v OFS=, '
NR==1 {
    print $1,$2,$3, "CTEXT","XVALUE"
    for (i = 4; i <= NF; i++) a[i]=$i
    am=NF; next
}
{
    if (am < NF) {
        print "record "NR" too many values for text" > "/dev/stderr"
        next
    }
    for (i = 4; i <= am; i++) {
        if (i > NF) {
            print "record "NR" insufficient value" > "/dev/stderr"
            break
        }
        print $1,$2,$3,a[i],$i
    }
}' input.csv
awk-F,-v OFS=,'
NR==1{
打印$1、$2、$3、“CTEXT”、“XVALUE”
对于(i=4;i)/dev/stderr”
下一个
}
对于(i=4;i NF){
打印“记录”NR“值不足”>“/dev/stderr”
打破
}
打印$1、$2、$3、a[i]、$i
}
}'input.csv

  • 您需要将
    i
    增加到
    NR
    am
    (即使您将Solaris awk切换到gawk或nawk,也会出现 仍然存在一些问题。请尝试以下操作:

    awk -F, -v OFS=, '
    NR==1 {
        print $1,$2,$3, "CTEXT","XVALUE"
        for (i = 4; i <= NF; i++) a[i]=$i
        am=NF; next
    }
    {
        if (am < NF) {
            print "record "NR" too many values for text" > "/dev/stderr"
            next
        }
        for (i = 4; i <= am; i++) {
            if (i > NF) {
                print "record "NR" insufficient value" > "/dev/stderr"
                break
            }
            print $1,$2,$3,a[i],$i
        }
    }' input.csv
    
    awk-F,-v OFS=,'
    NR==1{
    打印$1、$2、$3、“CTEXT”、“XVALUE”
    对于(i=4;i)/dev/stderr”
    下一个
    }
    对于(i=4;i NF){
    打印“记录”NR“值不足”>“/dev/stderr”
    打破
    }
    打印$1、$2、$3、a[i]、$i
    }
    }'input.csv
    
    • 您需要将
      i
      增加到
      NR
      am
      (不是<但是类似的值

      $ awk -F, 'BEGIN {OFS=FS} 
                 NR==1 {n=split($0,h); 
                        print $1,$2,$3,"CTEXT","XVALUE"; 
                        next} 
                 n!=NF {print n<NF?"too many":"not enough"; 
                        exit} 
                       {for(i=4;i<=NF;i++) print $1,$2,$3,h[i],$i}' file
      
      C1,C2,C3,CTEXT,XVALUE
      x1,x2,x3.1,Cv1,1.1
      x1,x2,x3.1,Cv2,1.2
      x1,x2,x3.1,Cv3,1.3
      x1,x2,x3.1,Cv4,1.4
      x1,x2,x3.2,Cv1,2.1
      x1,x2,x3.2,Cv2,2.2
      x1,x2,x3.2,Cv3,2.3
      x1,x2,x3.2,Cv4,2.4
      x1,x2,x3.3,Cv1,3.1
      x1,x2,x3.3,Cv2,3.2
      x1,x2,x3.3,Cv3,3.3
      x1,x2,x3.3,Cv4,3.4
      
      $awk-F,'BEGIN{OFS=FS}
      NR==1{n=split($0,h);
      打印$1、$2、$3、“CTEXT”、“XVALUE”;
      下一个}
      n!=NF{print n类似这样的东西

      $ awk -F, 'BEGIN {OFS=FS} 
                 NR==1 {n=split($0,h); 
                        print $1,$2,$3,"CTEXT","XVALUE"; 
                        next} 
                 n!=NF {print n<NF?"too many":"not enough"; 
                        exit} 
                       {for(i=4;i<=NF;i++) print $1,$2,$3,h[i],$i}' file
      
      C1,C2,C3,CTEXT,XVALUE
      x1,x2,x3.1,Cv1,1.1
      x1,x2,x3.1,Cv2,1.2
      x1,x2,x3.1,Cv3,1.3
      x1,x2,x3.1,Cv4,1.4
      x1,x2,x3.2,Cv1,2.1
      x1,x2,x3.2,Cv2,2.2
      x1,x2,x3.2,Cv3,2.3
      x1,x2,x3.2,Cv4,2.4
      x1,x2,x3.3,Cv1,3.1
      x1,x2,x3.3,Cv2,3.2
      x1,x2,x3.3,Cv3,3.3
      x1,x2,x3.3,Cv4,3.4
      
      $awk-F,'BEGIN{OFS=FS}
      NR==1{n=split($0,h);
      打印$1、$2、$3、“CTEXT”、“XVALUE”;
      下一个}
      
      n!=NF{printn@AmadanPivot与transpose不同。@Barmar:True。我的不好。我没有注意到数据,将标题视为正确。这看起来像是旧的awk错误消息。请尝试
      nawk
      ,或
      gawk
      /usr/xpg4/bin/awk
      (编辑Q以显示
      uname-srv
      )的输出)。祝您好运。请选择一种常见的格式化代码样式,并将其用于您的脚本。您现在拥有的某些行上的多个语句和随意的缩进使得您的脚本不必要地难以理解。此外-awk支持
      for
      循环,因此您可以编写类似
      for的语句(i=4;i@AmadanPivot与transpose不同。@Barmar:True。我的不好。我没有注意到数据,将标题视为正确。这看起来像是旧的awk错误消息。请尝试
      nawk
      ,或
      gawk
      /usr/xpg4/bin/awk
      (编辑Q以显示
      uname-srv
      )的输出)。祝您好运。请选择一种常见的格式化代码样式,并将其用于您的脚本。您现在拥有的某些行上的多个语句和随意的缩进使得您的脚本不必要地难以理解。此外-awk支持
      for
      循环,因此您可以编写类似
      for的语句(i=4;i@wina如果您指的是第2行附近的消息
      awk:syntax error awk:bailing out in line 2
      ,您首先需要更改为其他
      awk
      ,如@sheller comments。我上面的代码并不能解决错误本身。@wina很高兴知道它的工作原理。顺便说一句,您几乎接近正确的位置,这让人惊讶尽管您无法运行,但请回答。干杯!@wina如果您指的是消息
      awk:syntax error靠近第2行awk:bailing out靠近第2行
      ,由于
      相同的错误
      ,您首先需要更改为其他
      awk
      作为@sheller注释。我上面的代码本身并不能解决错误。@wina很高兴知道它的工作原理。顺便说一句,这是令人惊讶的尽管你无法运行,但你几乎接近正确答案。干杯!