将列粘贴到循环中的现有文件

时间:2012-10-16 10:33:05

标签: bash shell unix paste

我在bash循环中使用paste命令将新列添加到CSV文件中。我想重用CSV文件。目前我正在使用临时文件来完成此任务:

while [ $i -le $max ]
    do
        # create text from grib2
        wgrib2 -d 1.$(($i+1)) -no_header myGribFile.grb2 -text tmptxt.txt

        #paste to temporary file
        paste -d, existingfile.csv tmptxt.txt > tmpcsv.csv  

        #overwrite old csv with new csv
        mv tmpcsv.csv existingfile.csv

        ((i++))
    done

添加一些列后,副本变得越来越慢,因为文件变得越来越大(每个tmptxt.txt大约有2 MB,增加到大约100 MB)。

tmptxt.txt是一个普通的txt文件,每行有一列和一个值:

1
2
3
.
.

existingfile.csv将是

1,1,x
2,2,y
3,3,z
.,.,.
.,.,.

有没有办法使用paste命令将列添加到现有文件?或者还有其他方法吗?

由于

2 个答案:

答案 0 :(得分:6)

将操作拆分为2是否可行?生成 all 中间文件的一步;另一个用于生成 all 最终输出文件。我们的想法是避免重复读取和重写最终文件。

对脚本的更改将是这样的:

while [ $i -le $max ]
do
    n=$(printf "%05d" $i)    # to preserve lexical order if $max > 9
    # create text from grib2
    wgrib2 -d 1.$(($i+1)) -no_header myGribFile.grb2 -text tmptxt$n.txt
    ((i++))
done

#make final file
paste -d, existingfile.csv tmptxt[0-9]*.txt > tmpcsv.csv  

#overwrite old csv with new csv
mv tmpcsv.csv existingfile.csv

答案 1 :(得分:0)

假设程序输出的行数是恒定的,并且等于existingfile.csv中的行数(由于您使用的是paste,应该是这种情况)

免责声明:我不确定这是否会加快速度(取决于io重定向>>是否只写入文件一次)。无论如何试试让我知道。

所以基本的想法是

  1. 在循环完成后将输出一次性附加(注意更改:wgrib现在打印到- stdout

  2. 使用awk将每个linenum行(linenum作为existingfile.csv中的行数)移动到第一行linenum行的结尾

    保存到tempcsv.csv(因为我无法找到保存在同一文件中的方法)

  3. 重命名为/覆盖existingfile.csv

  4. while [ $i -le $max ]; do
      # create text from grib2
      wgrib2 -d 1.$(($i+1)) -no_header myGribFile.grb2 -text -
    
      ((i++))
    done >> existingfile.csv
    
    awk -v linenum=4 '
      { array[FNR%linenum]=array[FNR%linenum]","$0 } 
      END { for(i=1;i<linenum;i++) print array[i%linenum] }
    ' existingfile.csv > tempcsv.csv
    
    mv tempcsv.csv existingfile.csv
    

    如果这是我想象的那样(内部),你应该有2次写入existingfile.csv而不是$max次写入。所以希望这会加快速度。