KSH Shell 脚本 - 按行块处理文件

KSH Shell script - Process file by blocks of lines

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

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

i=1
while [[ `wc -l /path/to/block.file | awk -F' ' '{print }'` -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

在启动上述脚本之前,我执行了一个手动操作 'first injection':head -$lc /path/to/source.file | tail -1000 > /path/to/temp.source.file

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

在此先感谢大家

看看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 }'` -gt $((i * 1000)) ]]

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

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

在 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

效果很好

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

#!/usr/bin/ksh

range=
file=

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