【问题标题】:How to parse through a csv file by awk?如何通过awk解析csv文件?
【发布时间】:2015-05-08 22:42:00
【问题描述】:

实际上,我有 csv 文件,其中假设有 20 个标题,并且它们在特定记录的下一行中具有这些标题的相应值。 示例:源文件

Age,Name,Salary
25,Anand,32000

我希望我的输出文件采用这种格式。 示例:输出文件

Age
25
Name
Anand
Salary
32000

那么要使用哪个 awk/grep/sed 命令呢?

【问题讨论】:

  • 向我们展示你到目前为止的尝试。
  • 您的输入是只有 2 行,还是有多对标题/数据行?

标签: bash csv awk sed grep


【解决方案1】:

我会说

awk -F, 'NR == 1 { split($0, headers); next } { for(i = 1; i <= NF; ++i) { print headers[i]; print $i } }' filename

那是

NR == 1 {                       # in the first line
  split($0, headers)            # remember the headers
  next                          # do nothing else
}
{                               # after that:
  for(i = 1; i <= NF; ++i) {    # for all fields:
    print headers[i]            # print the corresponding header
    print $i                    # followed by the field
  }
}

附录:强制性的、疯狂的 sed 解决方案(不推荐用于生产用途;为娱乐而非盈利而编写):

sed 's/$/,/; 1 { h; d; }; G; :a s/\([^,]*\),\([^\n]*\n\)\([^,]*\),\(.*\)/\2\4\n\3\n\1/; ta; s/^\n\n//' filename

工作原理如下:

s/$/,/         # Add a comma to all lines for more convenient processing
1 { h; d; }    # first line: Just put it in the hold buffer
G              # all other lines: Append hold bufffer (header fields) to the
               # pattern space
:a             # jump label for looping

               # isolate the first fields from the data and header lines,
               # move them to the end of the pattern space
s/\([^,]*\),\([^\n]*\n\)\([^,]*\),\(.*\)/\2\4\n\3\n\1/
ta             # do this until we got them all
s/^\n\n//      # then remove the two newlines that are left as an artifact of
               # the algorithm.

【讨论】:

    【解决方案2】:

    这是一个awk

    awk -F, 'NR==1{for (i=1;i<=NF;i++) a[i]=$i;next} {for (i=1;i<=NF;i++) print a[i] RS $i}' file
    Age
    25
    Name
    Anand
    Salary
    32000
    

    第一个 for 循环将标头存储在数组 a
    第二个for 循环打印来自数组a 的标题以及相应的数据。

    【讨论】:

      【解决方案3】:

      将 GNU awk 4.* 用于二维数组:

      $ awk -F, '{a[NR][1];split($0,a[NR])} END{for (i=1;i<=NF;i++) for (j=1;j<=NR;j++) print a[j][i]}' file
      Age
      25
      Name
      Anand
      Salary
      32000
      

      一般转置行和列:

      $ cat file
      11 12 13
      21 22 23
      31 32 33
      41 42 43
      

      使用 GNU awk:

      $ awk '{a[NR][1];split($0,a[NR])} END{for (i=1;i<=NF;i++) for (j=1;j<=NR;j++) printf "%s%s", a[j][i], (j<NR?OFS:ORS)}' file
      11 21 31 41
      12 22 32 42
      13 23 33 43
      

      或使用任何 awk:

      $ awk '{for (i=1;i<=NF;i++) a[NR][i]=$i} END{for (i=1;i<=NF;i++) for (j=1;j<=NR;j++) printf "%s%s", a[j][i], (j<NR?OFS:ORS)}' file
      11 21 31 41
      12 22 32 42
      13 23 33 43
      

      【讨论】:

        猜你喜欢
        • 2016-05-04
        • 1970-01-01
        • 2023-03-06
        • 2021-03-04
        • 1970-01-01
        • 2016-05-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多