Bash:处理I/O最有效的方法是什么?

Bash: what is the most efficient way to handle I/O?

我有一个 bash 脚本,它可以进行大量的字符串操作。据我所知,从文件中读取很慢。因此,我没有在每次需要它的内容时都这样做,而是在脚本的开头阅读了整个文件

readarray -t lines < "$filename"

但每次我需要将行输入到接受输入的程序(例如,awkcutgrep)时,我无论如何都必须打印它们并创建一条管道。这是一个在文件中找到包含冒号的第一行的示例

line=$(printf -- '%s\n' "${lines[@]}" | grep -n -m 1 :)

所以我开始怀疑,我不是只是通过额外调用 echo 并创建管道来让它变慢吗?处理这种情况的最佳方法是什么?

您可以使用 bash-特定的 <<< 运算符将变量通过管道传输到命令中,而无需 echo/printf-ing 它们:

λ printf "test\nline\n" > file
λ cat file
test
line
λ readarray -t lines < file
λ wc -c <<< "${lines[0]}"
5
λ printf "%s" "${lines[0]}"
test

此外,假设您不需要一次需要所有内容,您可以直接使用类似这样的东西来使用它,而不是将文件读入变量:

while read -r line; do
    grep -n -m1 ':' <<< "$line" && {
        echo "Got colon"
        break
    }
done < filename

如果你想看哪个更快,可以试试time:

time readarray -t lines < "$filename"

time line=$(printf -- '%s\n' "${lines[@]}" | grep -n -m 1 :)

这会给你以毫秒为单位的时间,让你看看哪个更快。