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

时间:2017-08-07 08:22:17

标签: bash shell loops ksh tail

我正在尝试在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

有关如何在处理源文件中的最后几行后停止脚本的想法吗?

先谢谢你们所有人

3 个答案:

答案 0 :(得分:0)

查看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

或者提取第3个块例如(1000这里不是行数,它是块数,或者块是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 )

答案 1 :(得分:0)

根据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

这很有效

答案 2 :(得分:0)

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

#!/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