我从while read line
指定的文本文件中读取了一个bash $filename
块:
IFS=''
while read -r line
do
...
done < $filename
我不是每次都读取整个文件,而是根据提供给脚本的参数在重定向中提供不同的输入。
done < "$filename"
done < <(tail -n +"$x" "$filename")
done < <(tail -n +"$x" "$filename" | head -n "$y")
done < <(head -n "$y" "$filename")
如何提前将这些输入分配给变量以供while循环读取?
我的输入文件大约为4GB,有58M行(所有长度都不同),并且可能会不时增大或缩小。阅读https://unix.stackexchange.com/questions/47407/cat-line-x-to-line-y-on-a-huge-file似乎tail | head
是从文件中间读取的最快方法,因此,鉴于文件大小,我故意避免awk
和{{1}在大多数情况下。
答案 0 :(得分:3)
您的数据太大,无法完整阅读。好消息是进程替换的内容是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<&-
答案 1 :(得分:1)
我可能会将所有这些作为循环条件的一部分处理,并使用明确维护的行计数器。
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
本身的问题。