如何将表达式分配给读取行的变量?

How can I assign expressions to a variable for read line?

我有一个 bash while read line 块从 $filename 指定的文本文件中读取:

IFS=''
while read -r line
do
    ...
done < $filename

我不想每次都读取整个文件,而是想根据提供给脚本的参数在重定向中提供不同的输入。

如何提前将这些输入分配给变量以供 while 循环读取?


我的输入文件大约有 4GB,有一些 58M 行(所有行都有不同的长度),并且可能会不时地增长或缩小。读取 https://unix.stackexchange.com/questions/47407/cat-line-x-to-line-y-on-a-huge-file 似乎 tail | head 是从文件中间读取的最快方法,因此考虑到文件大小,我故意避免 awksed大部分。

我可能会将所有这些作为循环条件的一部分来处理,并带有一个明确维护的行计数器。

start=10
end=30
i=0
while ((i <= end )) && IFS= read -r line; do
   (( i++ >= start )) || continue
   ...
done < "$filename"

但是,如果您可能在开头跳过大量行,使用 sed

可能更有效
while IFS= read -r line; do
    ...
done < <(sed -n "$start,$stop p" "$filename")

awk:

while IFS= read -r line; do
   ...
done < <(awk -v start "$start" -v end "$end" 'NR >= start && NR <= end' "$filename")

这就提出了一个问题,即 while 循环的主体有多少可以移入 awk 本身。

您的数据太大,无法完整读取。好消息是一个进程替换的内容是一个shell脚本,所以你可以这样写:

while IFS= read -r line; do
    ...
done < <(

    if   [[ $x && $y ]];  then  tail -n +"$x" "$filename" | head -n "$y"
    elif [[ $x ]];        then  tail -n +"$x" "$filename"
    elif [[ $y ]];        then  head -n "$y" "$filename"
    else                        cat "$filename"
    fi

)

我不喜欢进程替换的一件事是代码遵循输入它的循环。要是先出现就好了。我认为这会起作用,但未经测试:

# set up file descriptor 3
exec 3< <(
    if   [[ $x && $y ]];  then  tail -n +"$x" "$filename" | head -n "$y"
    elif [[ $x ]];        then  tail -n +"$x" "$filename"
    elif [[ $y ]];        then  head -n "$y" "$filename"
    else                        cat "$filename"
    fi
)

# iterate over lines read from fd 3
while IFS= read -u3 -r line; do
    ...
done

# close fd 3
exec 3<&-