Se você tiver certeza de que algum caractere nunca ocorrerá no primeiro arquivo, poderá usar o comando colar.
Exemplo de colar usando a guia delimitador padrão:
paste file1 file2 | while IFS="$(printf '\t')" read -r f1 f2
do
printf 'f1: %s\n' "$f1"
printf 'f2: %s\n' "$f2"
done
Exemplo de colar usando @
:
paste -d@ file1 file2 | while IFS="@" read -r f1 f2
do
printf 'f1: %s\n' "$f1"
printf 'f2: %s\n' "$f2"
done
Observe que é suficiente se o caractere tiver a garantia de não ocorrer no primeiro arquivo. Isso ocorre porque read
ignorará IFS
ao preencher a última variável. Portanto, mesmo que @
ocorra no segundo arquivo, ele não será dividido.
Exemplo de colar usando alguns recursos bash para um código indiscutivelmente mais limpo:
while IFS=$'\t' read -r f1 f2
do
printf 'f1: %s\n' "$f1"
printf 'f2: %s\n' "$f2"
done < <(paste file1 file2)
Recursos do Bash usados: ansi c string ( $'\t'
) e substituição de processos ( <(...)
) para evite o loop while em um problema de subshell .
Se você não pode ter certeza de que algum caractere nunca ocorrerá em ambos os arquivos, então você pode usar os descritores de arquivos .
while true
do
read -r f1 <&3 || break
read -r f2 <&4 || break
printf 'f1: %s\n' "$f1"
printf 'f2: %s\n' "$f2"
done 3<file1 4<file2
Não testou muito. Pode quebrar em linhas vazias.
Os descritores de arquivo 0, 1 e 2 já são usados para stdin, stdout e stderr, respectivamente. Os descritores de arquivo de 3 e acima são (geralmente) gratuitos. O manual do bash avisa sobre o uso de descritores de arquivos maiores que 9, porque eles são "usados internamente".
Observe que os descritores de arquivos abertos são herdados para funções de shell e programas externos. Funções e programas que herdam um descritor de arquivo aberto podem ler (e gravar) o descritor de arquivo. Você deve tomar cuidado para fechar todos os descritores de arquivos que não são necessários antes de chamar uma função ou um programa externo.
Aqui está o mesmo programa acima, com o trabalho real (a impressão) separado do meta-trabalho (lendo linha por linha a partir de dois arquivos em paralelo).
work() {
printf 'f1: %s\n' "$1"
printf 'f2: %s\n' "$2"
}
while true
do
read -r f1 <&3 || break
read -r f2 <&4 || break
work "$f1" "$f2"
done 3<file1 4<file2
Agora fingimos que não temos controle sobre o código de trabalho e esse código, por qualquer motivo, tenta ler a partir do descritor de arquivo 3.
unknowncode() {
printf 'f1: %s\n' "$1"
printf 'f2: %s\n' "$2"
read -r yoink <&3 && printf 'yoink: %s\n' "$yoink"
}
while true
do
read -r f1 <&3 || break
read -r f2 <&4 || break
unknowncode "$f1" "$f2"
done 3<file1 4<file2
Aqui está um exemplo de saída. Observe que a segunda linha do primeiro arquivo é "roubada" do loop.
f1: file1 line1
f2: file2 line1
yoink: file1 line2
f1: file1 line3
f2: file2 line2
Aqui está como você deve fechar os descritores de arquivos antes de chamar o código externo (ou qualquer outro código).
while true
do
read -r f1 <&3 || break
read -r f2 <&4 || break
# this will close fd3 and fd4 before executing anycode
anycode "$f1" "$f2" 3<&- 4<&-
# note that fd3 and fd4 are still open in the loop
done 3<file1 4<file2