【问题标题】:Reading a file, block per block读取文件,每块块
【发布时间】:2014-10-29 22:39:03
【问题描述】:

我正在尝试制作一个高效的脚本来读取每个块的(大)文件块,并将最后一个读取块的第一行保存在文件中。 就我而言,如果我想通过管道将文件传输到程序,这非常有用。我可以停止它并稍后在它之前停止的同一行(即同一块行)启动它。

这是脚本:

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% 的效率。

你认为有更好的方法吗?

【问题讨论】:

  • 不打开文件并反复查找可能会有所帮助。不幸的是,除非您想从头开始按顺序阅读,否则在 bash 中这样做是不可能的。

标签: linux bash shell debian pipe


【解决方案1】:

也许这样可以:

#!/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 在这个索引处开始分配。

【讨论】:

  • 它就像一个魅力! mapfile 完美地完成了这项工作。请注意,我将量程调整为更高的值(10000)。
猜你喜欢
  • 2017-05-02
  • 2012-06-22
  • 1970-01-01
  • 1970-01-01
  • 2017-01-13
  • 2012-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多