【问题标题】:Append Columns to CSV in For Loop在 For 循环中将列附加到 CSV
【发布时间】:2021-01-16 17:24:42
【问题描述】:

我正在为我的脚本寻求帮助。我正在尝试遍历一堆 CSV 文件,删除第三列,并将其作为新列附加到输出文件中。到目前为止,这是我所拥有的:

#!/bin/bash

for n in ~/sampledir/*
do
    awk -F "," '{print $3","}' $n >> output.csv
done

输出如下:

Column3,
3,
33,
333,
3333,
33333,
Column3,
3,
33,
333,
3333,
33333,
Column3,
3,
33,
333,
3333,
33333,
Column3,
3,
33,
333,
3333,
33333,
Column3,
3,
33,
333,
3333,
33333,

我想要的是将新信息附加到列中的 CSV 中,而不是上面的输出,我想要这个:

Column3,Column3,Column3,Column3,Column3,Column3,
3,3,3,3,3,3,
33,33,33,33,33,33,
333,333,333,333,333,333,
3333,3333,3333,3333,3333,3333,
33333,33333,33333,33333,33333,33333,

任何指导都会有所帮助。谢谢大家。

【问题讨论】:

    标签: linux bash shell for-loop awk


    【解决方案1】:

    使用awk

    awk -F, '{row[FNR] = (FNR==NR? $3: row[FNR] FS $3)}
         END {for (i=1;i<=length(row);i++) print row[i]}' *.csv
    

    使用paste(bash shell):

    对于已知数量的文件,您可以拥有

    paste -d, <(cut -d, -f3 file1.csv) <(cut -d, -f3 file2.csv)
    

    但这不适用于未知数量的 csv 文件。一种骇人听闻的方式可能是:

    cmd="paste -d, "
    for f in *.csv; do cmd+=' <(cut -d, -f3 '"$f"')'; done
    eval "$cmd"
    

    但最好使用 awk。


    注意:您的 csv 文件不应在带引号的字段中嵌套分隔符。在这种情况下,您必须在 GNU awk 中使用更复杂的字段分隔符。

    【讨论】:

      【解决方案2】:

      如果您使用的 awk 是 gawk,您可以使用这样的 awk 脚本:

      BEGIN { 
          FS="," 
          file_num = 0
          max_num_rows = 0
      }
      
      BEGINFILE { file_num++  }
      
      { 
          data[FNR SUBSEP file_num] = $3 
          if (FNR > max_num_rows) { max_num_rows++ }
      }
      
      END {
      
          for (i = 1; i <= max_num_rows; i++) {
              printf data[i SUBSEP 1]
      
              for (j = 2; j <= file_num; j++) {
                  printf "," data[i SUBSEP j]
              }
              printf "\n"
          }
      }
      
      

      然后使用like:

      awk -f script.awk ~/sampledir/* > output.csv
      

      基本思路是将你想要的数据存储到一个多维的awk数组中,然后循环遍历行列并打印数据。如果你没有BEGINFILE 可用,你可以做一些额外的逻辑来做类似的事情。如果文件中的行数不同,这也应该有效。

      【讨论】:

      • 我将如何调整 gawk 脚本以添加文件名?基本上,我希望在每一列的顶部添加文件名,以便更容易识别哪个列属于哪个文件。
      • 您可以使用一个内置变量FILENAME。如果数据文件的第一行是标题,您可以将data[FNR SUBSEP file_num] = $3 更改为data[FNR SUBSEP file_num] = FNR == 1 ? FILENAME : $3
      猜你喜欢
      • 1970-01-01
      • 2020-09-25
      • 2017-08-20
      • 2020-03-26
      • 2015-04-27
      • 1970-01-01
      • 2019-08-04
      • 2017-03-06
      • 2018-12-11
      相关资源
      最近更新 更多