Je voulais savoir s'il existe un moyen de lire à partir de deux fichiers d'entrée dans une boucle imbriquée while une ligne à la fois. Par exemple, disons que j'ai deux fichiers FileA
et FileB
.
Déposer un:
[jaypal:~/Temp] cat filea
this is File A line1
this is File A line2
this is File A line3
FichierB:
[jaypal:~/Temp] cat fileb
this is File B line1
this is File B line2
this is File B line3
Exemple de script actuel:
[jaypal:~/Temp] cat read.sh
#!/bin/bash
while read lineA
do echo $lineA
while read lineB
do echo $lineB
done < fileb
done < filea
Exécution:
[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
Problème et sortie souhaitée:
Cela boucle complètement sur FileB pour chaque ligne de FileA. J'ai essayé d'utiliser continue, break, exit mais aucun d'eux n'est destiné à atteindre le résultat que je recherche. Je voudrais que le script lise une seule ligne du fichier A, puis une ligne du fichier B et quitte la boucle et continue avec la deuxième ligne du fichier A et la deuxième ligne du fichier B. Quelque chose de similaire au script suivant -
[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
Est-ce possible de le faire avec la boucle while?
bash
shell-script
io-redirection
jaypal singh
la source
la source
paste -d '\n' file1 file2
Réponses:
Si vous savez avec certitude qu'aucun caractère n'apparaîtra jamais dans le premier fichier, vous pouvez utiliser coller.
Exemple de collage à l'aide de l'onglet de délimitation par défaut:
Exemple de collage utilisant
@
:Notez que cela suffit si le caractère est garanti de ne pas apparaître dans le premier fichier. En effet
read
, ignoreraIFS
lors du remplissage de la dernière variable. Donc, même si cela@
se produit dans le deuxième fichier, il ne sera pas divisé.Exemple de collage utilisant certaines fonctionnalités bash pour un code sans doute plus propre:
Fonctionnalités bash utilisées: chaîne ansi c (
$'\t'
) et substitution de processus (<(...)
) pour éviter la boucle while dans un problème de sous-shell .Si vous ne pouvez pas être certain qu'aucun caractère n'apparaîtra jamais dans les deux fichiers, vous pouvez utiliser des descripteurs de fichiers .
Pas beaucoup testé. Peut se casser sur des lignes vides.
Les descripteurs de fichiers numéro 0, 1 et 2 sont déjà utilisés pour stdin, stdout et stderr, respectivement. Les descripteurs de fichiers à partir de 3 et plus sont (généralement) gratuits. Le manuel bash met en garde contre l'utilisation de descripteurs de fichiers supérieurs à 9, car ils sont "utilisés en interne".
Notez que les descripteurs de fichiers ouverts sont hérités des fonctions shell et des programmes externes. Les fonctions et programmes héritant d'un descripteur de fichier ouvert peuvent lire (et écrire dans) le descripteur de fichier. Vous devez prendre soin de fermer tous les descripteurs de fichiers qui ne sont pas requis avant d'appeler une fonction ou un programme externe.
Voici le même programme que ci-dessus avec le travail réel (l'impression) séparé du méta-travail (lecture ligne par ligne de deux fichiers en parallèle).
Maintenant, nous prétendons que nous n'avons aucun contrôle sur le code de travail et que ce code, pour une raison quelconque, essaie de lire à partir du descripteur de fichier 3.
Voici un exemple de sortie. Notez que la deuxième ligne du premier fichier est "volée" dans la boucle.
Voici comment fermer les descripteurs de fichiers avant d'appeler du code externe (ou tout autre code d'ailleurs).
la source
Ouvrez les deux fichiers sur des descripteurs de fichiers différents . Redirigez l'entrée du
read
intégré vers le descripteur auquel le fichier que vous souhaitez est connecté. Dans bash / ksh / zsh, vous pouvez écrire à laread -u 3
place deread <&3
.Cet extrait s'arrête lorsque le fichier le plus court a été traité. Voir Lecture de deux fichiers dans une boucle IFS while - Existe-t-il un moyen d'obtenir un résultat de différence nulle dans ce cas?si vous souhaitez continuer le traitement jusqu'à la fin des deux fichiers.
Voir aussi Quand utiliseriez-vous un descripteur de fichier supplémentaire? pour plus d'informations sur les descripteurs de fichiers, et Pourquoi est-ce que `alors que IFS = lire` est utilisé si souvent, au lieu de` IFS =; pendant la lecture .. »? pour une explication de
IFS= read -r
.la source
Je sais que vous voulez un script shell, mais vous voudrez peut-être jeter un œil à la
paste
commande.la source
paste
c'est cool aussi.Essayez la commande ci-dessous:
la source
Alternativement, je suppose que vous pouvez extraire le fichier dans une variable de tableau liant chaque ligne du fichier dans le tableau [line_of_file_index] en utilisant la commande mapfile de bash. Cependant, je ne sais pas si c'est uniquement pour Bash3 supérieur ou Bash4.
http://wiki.bash-hackers.org/commands/builtin/mapfile
la source