【问题标题】:KSH Shell script - Process file by blocks of linesKSH Shell 脚本 - 按行处理文件
【发布时间】:2017-08-07 08:22:16
【问题描述】:

我正在尝试在 KSH 环境中编写一个 bash 脚本,该脚本将遍历源文本文件并按行块处理它

到目前为止,我已经想出了这段代码,虽然它似乎无限期地运行,因为如果要求检索源文本文件中的行之外的行,tail 命令不会返回 0 行

i=1
while [[ `wc -l /path/to/block.file | awk -F' ' '{print $1}'` -gt $((i * 1000)) ]]

do
  lc=$((i * 1000))
  DA=ProcessingResult_$i.csv
  head -$lc /path/to/source.file | tail -1000 > /path/to/block.file
  cd /path/to/processing/batch
  ./process.sh #This will process /path/to/block.file
  mv /output/directory/ProcessingResult.csv /output/directory/$DA
  i=$((i + 1))
done

在启动上述脚本之前,我执行了手动“第一次注入”:head -$lc /path/to/source.file | tail -1000 > /path/to/temp.source.file

您知道如何在处理完源文件的最后几行后让脚本停止吗?

提前谢谢大家

【问题讨论】:

    标签: bash shell loops ksh tail


    【解决方案1】:

    如果您不想在开始处理每个块之前预先创建这么多临时文件,您可以尝试以下解决方案。处理大文件时可以节省大量空间。

    #!/usr/bin/ksh
    
    range=$1
    file=$2
    
    b=0; e=0; seq=1
    while true
    do
       b=$((e+1)); e=$((range*seq));
    
       sed -n ${b},${e}p $file > ${file}.temp
    
       [ $(wc -l ${file}.temp | cut -d " " -f 1) -eq 0 ] && break
    
       ## process the ${file}.temp as per your need ##
    
       ((seq++))
    done
    

    以上代码一次只生成一个临时文件。 您可以将范围(块大小)和文件名作为命令行参数传递给脚本。

    example: extractblock.sh 1000 inputfile.txt
    

    【讨论】:

    • 谢谢阿比斯,下次需要处理的时候再试试
    • 我已经将该脚本用于另一个处理,并且运行良好。再次感谢
    【解决方案2】:

    看看man split

    NAME
       split - split a file into pieces
    
    SYNOPSIS
       split [OPTION]... [INPUT [PREFIX]]
    
       -l, --lines=NUMBER
              put NUMBER lines per output file
    

    例如

    split -l 1000 source.file
    

    或者提取第三个chunk比如(这里的1000不是行数,是chunk的个数,或者一个chunk是source.file的1/1000)

    split -nl/3/1000 source.file
    

    条件说明:

    [[ `wc -l /path/to/block.file | awk -F' ' '{print $1}'` -gt $((i * 1000)) ]]
    

    也许它应该是source.file而不是block.file,它在大文件上效率很低,因为它会在每次迭代中读取(计算文件的行数);行数可以存储在一个变量中,在标准输入上使用 wc 也可以防止使用 awk:

    nb_lines=$(wc -l </path/to/source.file )
    

    【讨论】:

    • 谢谢 Nahuel,我会尝试使用 split 命令,然后在生成的文件上迭代处理脚本,我会 +1,但到目前为止我没有足够的权限...
    【解决方案3】:

    在 Nahuel 的建议下,我能够像这样构建脚本:

    i=1
    cd /path/to/sourcefile/
    split source.file -l 1000 SF
    
    for sf in /path/to/sourcefile/SF*
    do
      DA=ProcessingResult_$i.csv
      cd /path/to/sourcefile/
      cat $sf > /path/to/block.file
      rm $sf
      cd /path/to/processing/batch
      ./process.sh #This will process /path/to/block.file
      mv /output/directory/ProcessingResult.csv /output/directory/$DA
      i=$((i + 1))
    done
    

    效果很好

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      • 2012-01-08
      • 2014-06-05
      • 1970-01-01
      • 1970-01-01
      • 2018-04-10
      相关资源
      最近更新 更多