2011-10-01 15 views
30

Tengo un trabajo sucio que hacer, por lo que un guión Bash parece ser una buena opción. Soy nuevo en Bash, y la experiencia me frustra.Bash: lea un archivo línea por línea y procese cada segmento como parámetros a otro prog

El archivo mapfiles.txt se compone de las siguientes líneas. Cada línea tiene cuatro segmentos separados por un espacio en blanco. Cada segmento representa un parámetro de entrada para un nombre de programa externo 'prog'. Por ejemplo, "cm19_1.png" es el nombre de archivo , "0001" el índice de, "121422481" la longitud, y "31035995" la latitud.

del archivo: mapfiles.txt

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

Quiero ejecutar comandos similares a cada línea. Como se muestra a continuación, el orden de los parámetros de entrada del programa es ligeramente diferente. Entonces tiene sentido escribir un script bash para manejar el trabajo repetido.

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

En general, la escritura del golpe funcionará de esta manera:

  1. Leer una línea de mapfiles.txt
  2. Dividir los segmentos
  3. llamada el prog con una orden de parámetro correcto

Aquí viene 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" 

Lo que esperaba es

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

el resultado real que tengo es

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

Los problemas que me confundió

  1. ¿Dónde está 'progresivo'?
  2. ¿Dónde está el espacio en blanco?
  3. ¿Qué pasa con el orden de los parámetros?

Hmm ... Escribí este script en mi Mac usando vim y lo copié en una caja Scientific Linux y una caja de gentoo. Estos tres chicos obtienen los mismos resultados ridículos.

+1

no es reproducible aquí. Busque errores tipográficos Además, en lugar de usar todos los cortes, simplemente usa 'read file key log lat'. * UPD * vea la respuesta. –

+0

Cuando se combina con ssh en el ciclo, échele un vistazo a esta pregunta: http://stackoverflow.com/questions/9393038/ssh-breaks-out-of-while-loop-in-bash – Christian

Respuesta

42

Se puede simplificar mucho esto:

while read file key log lat 
do 
    echo "$cmd" "$key" "$log" "$lat" "$file" 
done < "$input" 
+0

¡Qué divertido truco! . –

+6

Puede simplificarlo aún más. No necesita variables individuales para cada argumento: 'while read line; hacer eco $ cmd $ línea; done <"$ input" ' – Idelic

2

prog podrían haber desaparecido a causa $cmd no se exporta. Su versión de/bin/sh podría ejecutar la declaración while en un shell separado. Este no debería ser el caso, y este no es el caso para mi instalación de bash, pero quizás el suyo se comporte de maneras interesantes en este departamento.

UPD Veo que tiene varias cajas que dan los mismos resultados. Esto hace que la teoría de la subcadena sea poco probable. Quizás tengas algunos personajes divertidos en tu script y/o archivo fuente.

He copiado y pegado su script y su archivo de origen en mi caja de gentoo y da los resultados esperados. Tal vez deberías hacer lo mismo y comparar los archivos con los originales.

+2

Muchas gracias. Tu comentario me ayuda a descubrir qué es lo que REALMENTE sale mal. No es Bash Script - Lo pruebo en tres cajas diferentes - es el mapfiles.txt que sale mal. El archivo se genera en Windows y termina con^M en cada línea. Después de eliminar el^M, todo va bien. –

8

Usando GNU paralelo se puede hacer en una sola línea + que lograr que se haga en paralelo de forma gratuita:

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

Vea los videos de introducción para aprender más: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Cuestiones relacionadas