我正在尝试在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
有关如何在处理源文件中的最后几行后停止脚本的想法吗?
先谢谢你们所有人
答案 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