使用 Bash 读取多个文件
使用 bash 读取文件没什么大不了的:只需将输入重定向到脚本或将另一个命令的输出管道传输到脚本,或者如果文件名是预先确定的,则可以在脚本内部进行。您还可以使用进程替换从命令行传入打开的文件(实际上是命令管道)。另一种选择是我在这里描述的,就是像在其他编程语言中一样,打开文件并根据需要读取(或写入)它们。
这里使用的机制利用了 bash 使用特定文件描述符重定向输入(或输出)的能力,其语法如下
n<file
n>file
n>>file
n<>file
这里的 "n" 是一个小整数,指定用于打开命名文件的文件描述符。 如果未指定 "n",则以下默认值适用
<file # same as 0<file
>file # same as 1>file
>>file # same as 1>>file
<>file # same as 0<>file
这当然是经常使用的标准重定向内容。
因此,假设 "n" 存在,那么似乎可以根据需要轻松打开文件并根据需要进行处理。 然而,如何实际做到这一点不太明显,但实际上非常简单
exec 7<file1
exec 8<file2
这打开了file1在文件描述符 7 上用于输入,以及file2在文件描述符 8 上。现在我们可以轻松地使用以下命令读取它们
read data1 <&7
read data2 <&8
请注意输入重定向到read使用另一种特殊形式,其中包括与号 (&) 以指定后面的是文件描述符而不是文件名。
使用 3-9 范围内的文件描述符。 小于 3 的文件描述符用于标准输入、输出和错误,大于 9 的文件描述符可能由 shell 内部使用。
虽然没有显式关闭文件的语法,但重新使用文件描述符会在打开新文件之前关闭该文件。 (08/21/2009:这是不正确的,存在关闭文件的语法,请参阅下面的评论 --Mitch)
为了安全起见,您可以执行以下操作来关闭文件
exec 7</dev/null
exec 8</dev/null
原因是exec是为了在当前 shell 而不是子 shell 中完成文件的打开,这样会在命令完成后立即关闭文件描述符(并不是说它在调用 shell 中可用)。 您可能还会惊讶地发现n<file本身不是语法错误,但它确实不是。
下面是一个执行所有这些操作的示例
#!/bin/bash
function readfiles()
{
local FD1=7
local FD2=8
local file1=$1
local file2=$2
local count1=0
local count2=0
local eof1=0
local eof2=0
local data1
local data2
# Open files.
# ***** 08/22/2009: See comments below for a way to avoid *****
# ***** hardcoding the file descriptors -- Mitch *****
exec 7<$file1
exec 8<$file2
while [[ $eof1 -eq 0 || $eof2 -eq 0 ]]
do
if read data1 <&$FD1; then
let count1++
printf "%s, line %d: %s\n" $file1 $count1 "$data1"
else
eof1=1
fi
if read data2 <&$FD2; then
let count2++
printf "%s, line %d: %s\n" $file2 $count2 "$data2"
else
eof2=1
fi
done
}
echo "Reading file1 and file2"
readfiles file1 file2
echo "Reading file3 and file4"
readfiles file3 file4
# vim: tabstop=4: shiftwidth=4: noexpandtab:
# kate: tab-width 4; indent-width 4; replace-tabs false;
顶部的函数读取文件,主要代码处理 2 个文件,然后处理 2 个不同的文件。 运行命令产生
$ bash readmult.sh
Reading file1 and file2
file1, line 1: f1 line 1
file2, line 1: f2 line 1
file1, line 2: f1 line 2
file2, line 2: f2 line 2
file1, line 3: f1 line 3
file2, line 3: f2 line 3
file1, line 4: f1 line 4
file2, line 4: f2 line 4
file1, line 5: f1 line 5
file2, line 5: f2 line 5
file1, line 6: f1 line 6
Reading file3 and file4
file3, line 1: f3 line 1
file4, line 1: f4 line 1
file3, line 2: f3 line 2
file4, line 2: f4 line 2
file3, line 3: f3 line 3
类似的过程可用于使用以下命令写入多个输出文件n>file或n>>file语法。 如果您在脚本中的许多不同位置将大量数据写入同一文件,这可能会节省时间。