web-dev-qa-db-fra.com

Bash: lire un fichier ligne par ligne et traiter chaque segment comme paramètres vers d'autres prog

J'ai un sale boulot à faire, donc un script Bash semble être un bon choix. Je suis nouveau chez Bash et l'expérience me rend un peu frustré.

Le fichier mapfiles.txt se compose des lignes suivantes. Chaque ligne a quatre segments séparés par un espace blanc. Chaque segment représente un paramètre d'entrée d'un nom de programme externe "prog". Par exemple, "cm19_1.png" est le nom de fichier, "0001" le index, "121422481" le longitude et "31035995" le latitude.

Fichier: mapfiles.txt

cm19_1.png 0001 121422481 31035995
cm19_2.png 0002 121423224 31035995
cm19_3.png 0003 121423967 31035995
…

Je veux exécuter des commandes similaires sur chaque ligne. Comme indiqué ci-dessous, l'ordre des paramètres d'entrée du prog est légèrement différent. Il est donc logique d'écrire un script bash pour gérer le travail répété.

[Usage] prog <index> <longitude> <latitude> <filename>
example: prog 0001 121422481 31035995 cm19_1.png

Généralement, le script bash fonctionnera de cette façon:

  1. Lire une ligne de mapfiles.txt
  2. Divisez les segments
  3. Appelez le prog avec un ordre de paramètre correct

Voici run.sh.

#!/bin/sh

input=mapfiles.txt
cmd=prog

while read line
do
        file=$(echo $line | cut -d' ' -f1)
        key=$(echo $line | cut -d' ' -f2)
        log=$(echo $line | cut -d' ' -f3)
        lat=$(echo $line | cut -d' ' -f4)
        echo $cmd $key $log $lat $file
done < "$input"

Ce que j'attendais c'est

prog 0001 121422481 31035995 cm19_1.png
prog 0002 121423224 31035995 cm19_2.png
prog 0003 121423967 31035995 cm19_3.png
… 

Le résultat RÉEL que j'ai obtenu est

 cm19_1.png21422481 31035995
 cm19_2.png21423224 31035995
 cm19_3.png21423967 31035995

Des problèmes qui m'ont dérouté

  1. Où est "prog"?
  2. Où est l'espace blanc?
  3. Quel est le problème avec l'ordre des paramètres?

Hmm… J'ai écrit ce script sur mon Mac en utilisant vim et le copier dans une boîte Scientific Linux et une boîte gentoo. Ces trois gars obtiennent les mêmes sorties ridicules.

35
Jianwen W.

Vous pouvez simplifier cela beaucoup:

while read file key log lat
do
  echo "$cmd" "$key" "$log" "$lat" "$file"
done < "$input"
48
Mat

En utilisant GNU Parallèle, vous pouvez le faire en une seule ligne + vous le faites en parallèle gratuitement:

cat mapfile.txt | parallel --colsep '\s' prog {2} {3} {4} {1}

Regardez les vidéos d'introduction pour en savoir plus: http://www.youtube.com/watch?v=OpaiGYxkSuQ

9
Ole Tange

prog aurait pu disparaître car $cmd n'est pas exporté. Votre version de/bin/sh peut exécuter l'instruction while dans un shell distinct. Cela ne devrait pas être le cas, et ce n'est pas le cas pour mon installation de bash, mais peut-être que la vôtre se comporte de manière intéressante dans ce département.

UPD Je vois que vous avez plusieurs cases qui donnent les mêmes résultats. Cela rend la théorie du sous-shell peu probable. Peut-être avez-vous des personnages amusants dans votre script et/ou votre fichier source.

J'ai copié et collé votre script et votre fichier source dans ma boîte gentoo et cela donne les résultats attendus. Vous devriez peut-être faire de même et comparer les fichiers avec ceux d'origine.

2
n.m.