我正在尝试制作一个有效的脚本来读取每个块的(大)文件块,并将最后一个读取块的第一行保存在文件中。 在我的例子中,如果我想将文件传递给程序,这非常有用。我可以阻止它,然后在它之前停止的同一行开始(意思是相同的块行)。
这是脚本:
LINE_FILE=line-file
READ_FILE=the_file
BLOCK=1000
LN_SUP=$(cat $LINE_FILE)
####
trap "save_line ; exit" SIGHUP SIGINT SIGTERM SIGKILL
save_line()
{
echo $LN_SUP > $LINE_FILE
}
block_cat()
{
TEXT=$(tail -n+$LN_SUP $READ_FILE | head -n $BLOCK)
echo "$TEXT"
if [ -n "$TEXT" ]; then
return 0
else
return -1
fi
}
test()
{
return 1
}
file_cat()
{
>&2 echo "First line to read the file : $LN_SUP"
block_cat $READ_FILE
while [ $? -eq 0 ]; do
LN_SUP=$(($LN_SUP + $BLOCK)) #Remember the new first line of the block
block_cat $READ_FILE
done
}
这实际上有效,但没有我想象的那么快。
这用于将输出传输到aircrack-ng,我的效率几乎降低了18%。
您认为有更好的方法吗?
答案 0 :(得分:0)
也许会这样做:
#!/bin/bash
line_file=line-file
quantum=1000
file=the_file
die() {
(($#)) && printf '%s\n' "$@"
exit 1
}
[[ -e $line_file ]] || echo "0" > "$line_file"
[[ -f $line_file ]] || die "File \`$line_file' not found"
[[ -r $line_file ]] || die "Can't read file \`$line_file'"
read current_line < "$line_file"
[[ $current_line = *([[:digit:]]) ]] || die "Error in file \`$line_file'"
((current_line=10#$current_line))
callback() {
printf '%s\n' "${mary[@]}"
mary=()
echo "$1" > "$line_file"
}
mapfile -O "$current_line" -s "$current_line" -t -c "$quantum" -C callback mary < "$file" && callback
它使用mapfile
及其很少使用(并且不是众所周知的)回调和量子的东西。如果第一个块只有999行,请不要感到惊讶。其他的是1000行长。有这方面的解决方法,但我不认为这对你的情况非常重要。
我还没有真正尝试过,如果有任何缺陷,请告诉我。
这里有许多关于你原始问题的无用线。但是,这些只是错误处理和常规检查,不能伤害。你只能专注于此:
callback() {
printf '%s\n' "${mary[@]}"
mary=()
echo "$1" > "$line_file"
}
mapfile -O "$current_line" -s "$current_line" -t -c "$quantum" -C callback mary < "$file" && callback
因此,每次读取quantum
(此处为1000)行时,都会调用回调,第一个参数设置为将在回调后设置的数组索引。在此回调中,我们只是转储数组的内容,清除此数组,并在line_file
中保存文件的位置。就这么简单。要获得文件的结尾,我们最后一次调用callback
。
执行mapfile
时,-s "$current_line"
告诉mapfile
跳过那么多行,-O "$current_line"
告诉mapfile
开始在此索引处分配。