【问题标题】:Parsing multiple CSV files in bash by pattern with counter通过带有计数器的模式在bash中解析多个CSV文件
【发布时间】:2020-04-27 00:44:03
【问题描述】:

假设我有文件

  • 报告-x-1.csv
  • report-x-2.csv
  • report-x-3.csv
  • report-y-1.csv
  • report-y-2.csv
  • report-y-3.csv

我得到了第二列的最后一个值,有点格式

 awk -v max=0 '{if($1>max){want=$2; max=$1}}END{print "x:";print want} ' report-x-1.csv >> test.txt

如何处理任意数量的 .csv 文件并在顶部设置计数器?

awk -v max=0 '{if($1>max){want=$2; max=$1}}END{print "x:";print want} ' report-x-* >> test.txt

只为第一个文件做一些事情。

我最终需要的是一个像这样的 .csv,但输入文件的数量是任意的:

x1 , 300
x2 , 250
x3 , 300
y1 , 270
y2 , 250
y3 , 280

编辑:
我还没有详细尝试每个想法,为了更清楚,这里有两个示例文件

https://pastebin.com/VMb32ULc

https://pastebin.com/qXQnagQ9

这些文件可以命名为 report-x-1.csv 和 report-y-1.csv,输出文件应包含两行 x-1: 156. ... 和 y-1: 300. .. ..(这是最后一行第二列)
该解决方案应该适用于上述多个输入文件。

【问题讨论】:

  • if($1>max){want=$2; max=$1} 看起来你想要最大值,而不是最后一个值。
  • @blackbaddl :awk 的默认字段分隔符是空格,所以 - 如果我拿你的示例文件 - echo 'x1 , 300' | awk '{print $2}' 将输出一个逗号,而不是第二个 CSV 列中的数字。跨度>
  • @KamilCuk 是的,你是对的,但无论如何第一列是一个上升计数器

标签: bash shell csv unix awk


【解决方案1】:

请您尝试以下操作。由于没有提供样品,因此无法对其进行测试。但这应该比遍历所有 csv 文件并在每次迭代中调用 awkfor 循环更快。

以下是本计划中的注意事项:

  • 无需使用for 循环遍历.csv 文件,因为awk 可以做到这一点。
  • OP 的代码不负责从文件名中获取 xy 值,我也添加了该逻辑。
  • 也可以根据需要在代码BEGIN部分设置输出文件名。


awk -v max=0 '
BEGIN{
  OFS=" , "
  output_file="output.txt"
}
FNR==1{
  if(want){
    print output":"ORS want > (output_file)    
  }
  split(FILENAME,array,"[-.]")
  output=array[2] array[3]
  want=max=""
}
{
  if($1>max){
    want=$2
    max=$1
  }
}
END{
  print output":"ORS want > (output_file)
}
' *.csv

由 OP 修正的错字

【讨论】:

    【解决方案2】:

    要为目录中的每个文件运行脚本,您可以使用管道传输文件名并使用xargs -n1

    echo report-x-*.csv | xargs -n1 awk -v max=0 '{if($1>max){want=$2; max=$1}}END{print "x:";print want}' >> test.txt
    

    【讨论】:

      【解决方案3】:

      也许可以试试:

      for file in $(ls)
      do
          echo 'Doing something to file:' $file
          awk -v max=0 '{if($1>max){want=$2; max=$1}}END{print "x:";print want} ' $file >> test.txt
      done
      

      或许:

      for file in $(ls)
      do
          if [[ $file == *.csv ]]; then
              echo 'Doing something to file:' $file
              awk -v max=0 '{if($1>max){want=$2; max=$1}}END{print "x:";print want} ' $file >> test.txt
          fi
      done
      

      【讨论】:

      • Why not parse lsfor file in $(ls) 如果文件名中有任何空格和其他字符,则会中断,并且未引用的 $file 可能会导致错误。只需使用 globbing for file in * 并引用您的变量。 for file in $(ls) do if [[ $file == *.csv ]]; 为什么不首先 for i in *.csv
      猜你喜欢
      • 1970-01-01
      • 2014-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-16
      • 2015-12-04
      • 1970-01-01
      • 2021-03-04
      相关资源
      最近更新 更多