Answers:
首先,不要读取for的行,因为通过单词拆分读取行存在一些不可避免的问题。
假设文件长度相等,或者如果只想循环直到读取两个文件中的较短文件,则可以采用简单的解决方案。
while read -r x && read -r y <&3; do
...
done <file1 3<file2
由于何时read
返回false以及其他一些原因,很难将更通用的解决方案放在一起。此示例可以读取任意数量的流,并在输入最短或最长后返回。
#!/usr/bin/env bash
# Open the given files and assign the resulting FDs to arrName.
# openFDs arrname file1 [file2 ...]
openFDs() {
local x y i arr=$1
[[ -v $arr ]] || return 1
shift
for x; do
{ exec {y}<"$x"; } 2>/dev/null || return 1
printf -v "${arr}[i++]" %d "$y"
done
}
# closeFDs FD1 [FD2 ...]
closeFDs() {
local x
for x; do
exec {x}<&-
done
}
# Read one line from each of the given FDs and assign the output to arrName.
# If the first argument is -l, returns false only when all FDs reach EOF.
# readN [ -l ] arrName FD1 [FD2 ...]
readN() {
if [[ $1 == -l ]]; then
local longest
shift
else
local longest=
fi
local i x y status arr=$1
[[ -v $arr ]] || return 1
shift
for x; do
if IFS= read -ru "$x" "${arr}[i]" || { unset -v "${arr}[i]"; [[ ${longest+_} ]] && return 1; }; then
status=0
fi
((i++))
done
return ${status:-1}
}
# readLines file1 [file2 ...]
readLines() {
local -a fds lines
trap 'closeFDs "${fds[@]}"' RETURN
openFDs fds "$@" || return 1
while readN -l lines "${fds[@]}"; do
printf '%-1s ' "${lines[@]}"
echo
done
}
{
readLines /dev/fd/{3..6} || { echo 'error occured' >&2; exit 1; }
} <<<$'a\nb\nc\nd' 3<&0 <<<$'1\n2\n3\n4\n5' 4<&0 <<<$'x\ny\nz' 5<&0 <<<$'7\n8\n9\n10\n11\n12' 6<&0
# vim: set fenc=utf-8 ff=unix ts=4 sts=4 sw=4 ft=sh nowrap et:
因此,取决于是否readN
获取-l
,输出为
a 1 x 7
b 2 y 8
c 3 z 9
d 4 10
5 11
12
要么
a 1 x 7
b 2 y 8
c 3 z 9
不必在一个循环中读取多个流而又不能将所有内容保存到多个数组中并不是很常见的事情。如果您只想读取数组,则应该看一下mapfile
。
||
“目录”操作符短路像大多数语言。当然,这已经被回答了一千遍了……
做完 完成-您需要两个要点和两个要点:
for i in $(< file1); do for j in $(< file2); do echo $i $j;done ; done
当然,file2对file1中的每个单词处理一次。
在大多数情况下,使用<代替cat应该不会显着提高性能。不涉及子流程。(不确定最后一句话)。
未压缩:
for i in $(< file1)
do
for j in $(< file2)
do
echo $i $j
done
done
如果您不喜欢阅读单词,但喜欢读线,并保留空白,请使用while并阅读:
while read line; do while read second; do echo "${line}${second}"; done <file2 ; done <file1
如果要附加两个文件,而不是嵌套它们:
cat file1 file2 | while read line; do echo "${line}"; done
如果要压缩2个文件,请使用粘贴:
paste file1 file2
<
相比cat
。而且我不确定如何测试它,以及何时将在语义上变得重要。如果调用管道,则子流程中的变量不会冒泡至主流程,但此处没有变量。我严厉批评了句子,直到有人可以澄清为止。
while
具有Interesitng语法。您可以在do ... while
循环之前放置多个命令,有问题的情况可能需要使用此功能,具体取决于您的以下特定要求:是读取到最长文件的末尾,还是只读取最短文件的末尾。
例如,read || read
根本不起作用(根据问题的要求),例如,当第一个文件的读取为时true
,第二个文件的读取将被跳过,直到从头到尾读取第一个文件为止...然后,因为状态为仍然是true
,while循环继续并从头到尾读取第二个文件。
read && read
如果您只想读取最短的文件,它将同时(同步)读取文件。但是,如果您想将两个文件都读取到eof
,则需要满足while's
语法要求,即。由命令立即之前的do while
产生非零返回代码循环打破while循环的进行。
这是一个如何将两个文件读到eof的示例
while IFS= read -r line3 <&3 || ((eof3=1))
IFS= read -r line4 <&4 || ((eof4=1))
!((eof3 & eof4))
do
echo "$line3, $line4"
done 3<file3 4<file4
(您可能需要在读取前测试eof3和eof4,但是总的思路就存在了,尤其是在最终的true / false条件下。
||
对我不起作用。它先处理file1 然后再处理 file2,但确实使文件保持同步&&
,并在第一次eof时退出while循环。