Eu queria saber se existe alguma maneira de ler dois arquivos de entrada em um loop aninhado while, uma linha por vez. Por exemplo, digamos que eu tenho dois arquivos FileA
e FileB
.
Arquivo A:
[jaypal:~/Temp] cat filea
this is File A line1
this is File A line2
this is File A line3
PastaB:
[jaypal:~/Temp] cat fileb
this is File B line1
this is File B line2
this is File B line3
Script de amostra atual:
[jaypal:~/Temp] cat read.sh
#!/bin/bash
while read lineA
do echo $lineA
while read lineB
do echo $lineB
done < fileb
done < filea
Execução:
[jaypal:~/Temp] ./read.sh
this is File A line1
this is File B line1
this is File B line2
this is File B line3
this is File A line2
this is File B line1
this is File B line2
this is File B line3
this is File A line3
this is File B line1
this is File B line2
this is File B line3
Problema e saída desejada:
Isso faz um loop sobre o FileB completamente para cada linha no FileA. Tentei usar continuar, interromper, sair, mas nenhum deles foi feito para alcançar a saída que estou procurando. Gostaria que o script lesse apenas uma linha do arquivo A e, em seguida, uma linha do arquivo B, saia do loop e continue com a segunda linha do arquivo A e a segunda linha do arquivo B. Algo semelhante ao script a seguir -
[jaypal:~/Temp] cat read1.sh
#!/bin/bash
count=1
while read lineA
do echo $lineA
lineB=`sed -n "$count"p fileb`
echo $lineB
count=`expr $count + 1`
done < filea
[jaypal:~/Temp] ./read1.sh
this is File A line1
this is File B line1
this is File A line2
this is File B line2
this is File A line3
this is File B line3
Isso é possível com o loop while?
bash
shell-script
io-redirection
jaypal singh
fonte
fonte
paste -d '\n' file1 file2
Respostas:
Se você tiver certeza de que algum caractere nunca ocorrerá no primeiro arquivo, poderá usar colar.
Exemplo de colagem usando a guia delimitador padrão:
Exemplo de colar usando
@
:Observe que é suficiente se for garantido que o caractere não ocorra no primeiro arquivo. Isso ocorre porque
read
será ignoradoIFS
ao preencher a última variável. Portanto, mesmo que@
ocorra no segundo arquivo, ele não será dividido.Exemplo de colagem usando alguns recursos do bash para um código sem dúvida mais limpo:
Recursos do Bash usados: string ansi c (
$'\t'
) e substituição do processo (<(...)
) para evitar o loop while em um problema de sub-shell .Se você não tiver certeza de que algum caractere nunca ocorrerá nos dois arquivos, use os descritores de arquivo .
Não testou muito. Pode quebrar em linhas vazias.
Os descritores de arquivo número 0, 1 e 2 já são usados para stdin, stdout e stderr, respectivamente. Os descritores de arquivos de 3 em diante são (geralmente) gratuitos. O manual do bash avisa sobre o uso de descritores de arquivo maiores que 9, porque eles são "usados internamente".
Observe que os descritores de arquivo aberto 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) no descritor de arquivo. Você deve fechar todos os descritores de arquivo que não são necessários antes de chamar uma função ou programa externo.
Aqui está o mesmo programa acima, com o trabalho real (a impressão) separado do meta-trabalho (lendo linha por linha de dois arquivos em paralelo).
Agora, fingimos que não temos controle sobre o código de trabalho e esse código, por qualquer motivo, tenta ler o descritor de arquivo 3.
Aqui está um exemplo de saída. Observe que a segunda linha do primeiro arquivo é "roubada" do loop.
Aqui está como você deve fechar os descritores de arquivo antes de chamar o código externo (ou qualquer outro código).
fonte
Abra os dois arquivos em descritores de arquivos diferentes . Redirecione a entrada do
read
interno para o descritor ao qual o arquivo que você deseja está conectado. No bash / ksh / zsh, você pode escrever emread -u 3
vez deread <&3
.Esse trecho para quando o arquivo mais curto é processado. Consulte Lendo dois arquivos em um loop IFS while - Existe uma maneira de obter um resultado zero diff neste caso? se você quiser continuar processando até o final dos dois arquivos.
Consulte também Quando você usaria um descritor de arquivo adicional? para obter informações adicionais sobre descritores de arquivos, e Por que `enquanto IFS = read` é usado com tanta frequência, em vez de` IFS =; enquanto lê ...? para uma explicação de
IFS= read -r
.fonte
Sei que você deseja um script de shell, mas pode dar uma olhada no
paste
comando.fonte
paste
é legal também.Experimente o comando abaixo:
fonte
Como alternativa, suponho que você possa inserir o arquivo em uma variável de matriz, amarrando cada linha do arquivo na matriz [line_of_file_index] usando o comando mapfile do bash. No entanto, não tenho certeza se é apenas para o Bash3 superior ou o Bash4.
http://wiki.bash-hackers.org/commands/builtin/mapfile
fonte