Shell scripting/es
¿Qué es esto?
Esta página contiene información acerca de cómo hacer un script para la línea de comandos (shell) para GRASS GIS.
La shell o intérprete de comandos para los sistemas operativos Unix o similares a Unix, es esencialmente un intérprete o procesador de comandos, es una interfaz basada en texto a través de la cual se pueden pasar instrucciones al sistema operativo de la computadora. Uno o más comandos pueden ser escritos en un script (normalmente en un archivo de texto) lo que, puede ser leido y ejecutado por la shell. La shell más usada probablemente es la bash.
El hacer un script (scripting) es el acto de diseñar, escribir, probar, eliminar bugs, y mantener una serie de comandos que realizan una función específica, ya sea sencilla o compleja.
<!Note, content below transfered here from the page GRASS and Shell.>
Haciendo un script para GRASS
Es bastante sencillo escribir un trabajo de GRASS como un script de Shell que lanza GRASS, hace la operación y limpia los archivos temporales.
Normalmente, es conveniente automatizar los trabajos repetitivos. GRASS puede ser controlado a través de scripts del usuario para facilitar el trabajo diario. ¿Cómo empezar?, el usar la línea de comandos de algún modo es como hacer scripts pero sin guardarlos - así que puedes escribir tu primer script guardando los comandos ejecutados en un archivo de texto (usa tu editor preferido, y de preferencia guarda el archivo en formato ASCII).
Nota importante: si no conoces sobre programación en la shell, y consideras aprenderlo, mejor echa un vistazo a Python (ej. GRASS and Python)...
Un primer script de shell de GRASS
Los comentarios deben empezar con el caracter '#'. La primer línea indica qué intérprete de shell se va a utilizar, aquí es "sh" , que está en el directorio /bi/.
Un ejemplo sencillo, a correr dentro de una sesión de GRASS:
#!/bin/sh
# mi primer script,
# copyright, año, Autor
# mostrar la configuración actual de la región
g.region -p
# salir con estatus 0 que significa "ok":
exit 0
Guarda este archivo como "myscript.sh" y correlo dentro de GRASS GIS desde la línea de comandos:
sh myscript.sh
Debe mostrar la configuración de la región actual, finalizar y regresar a la línea de comandos.
Para buscar errores en la shell (debugin), correr:
sh -x myscript.sh
Se mostrará cada línea lo cual ayuda a identificar errores.
Example 1 (simple): d.rast.region
Script para determinar la computational region/es a un mapa ráster ($1 es el parámetro para dar al script, aquí el nombre del mapa):
#!/bin/sh
# Autor: yo, hoy; copyright: GPL >= 2
# Propósito: script para determinar la región computacional a un mapa ráster
# Uso: d.rast.region rastermap
g.region rast=$1
d.erase
d.rast $1
exit 0
Usar la script en la localización "Nort Carolina" de GRASS 6:
d.mon x0
sh d.rast.region elev_state_500m
sh d.rast.region lsat7_2002_40
Ejemplo 2 (mejorado): d.rast.region
En este ejemplo, se asigna el primer parámetro ($1) dado al script (nombre del mapa) para una nueva variable que es más fácil para entender en el script. De nuevo, el script establece la región computacional a un mapa ráster, pero dice qué sucede:
#!/bin/sh
# Autor: yo, hoy; copyright: GPL >= 2
# Purprósito: script para establecer la región computacional a un mapa ráster
# Uso: d.rast.region rastermap
# ser cuidadoso de no dejar espacios en blanco en la siguiente línea:
map=$1
g.message message="Estableciendo la región computacional al mapa <$map>"
g.region rast=$map
d.erase
d.rast $map
exit 0
Usando el script en la localización "North Carolina": ver el ejemplo 1.
Ejemplo 3 (mejorado de nuevo): d.rast.region
Aquí se introduce la variable $0 que contiene el nombre del programa también como una prueba para mostrar el mapa especificado:
#!/bin/sh
# Autor: yo, hoy; copyright: GPL >= 2
# Propósito: script para definir la región computacional un mapa ráster
# Uso: d.rast.region rastermap
if [ $# -lt 1 ] ; then
echo "Parámetro no definido. Uso"
echo " $0 rastermap"
exit 1
fi
map=$1
g.message message="Definiendo la región computacional al mapa <$map>"
g.region rast=$map
d.erase
d.rast $map
exit 0
Para ver cómo funciona, es interesante usar el comprobador de errores de la shell (shell debugging):
d.mon x0
sh -x d.rast.region elev_state_500m
Ejemplo 4: manipulación de parámetros
Asume que quiere crear un script de shell para GRASS que tenga dos parámetro (coordenadas x y y) para calcular la cuenca relacionada con este punto de salida (r.water.outlet). En la shell, las variable $1 $2 y demás son parámetros que se pasan al script. Así, si se tiene un script llamado basin.sh y escribe
sh basin.sh -23.3 -47.7
La variable $1 será -23.3 y $2 será -47.6. En su script basin.sh puede usar la línea
r.water.outlet drainage="your_map" basin="basin_map" easting=$2 northing=$1
De la misma manera, se puede pasar un tercer parámetro para el nombre del mapa base, etc.
Sin embargo, es altamente recomendable usar g.parser para la manipulación de los parámetros. Es más fácil y se crea una interfaz gráfica de manera automática, incluso,¡los mensajes estándar aparecerán ya traducidos! Se puede clonar a partir de scripts ya existentes, vea aquí algunos ejemplo.
Usando la salida de los módulos de GRASS en el script
Algunas veces necesita usar la salida de un módulo para el siguiente paso en un script. La mayoría de los módulos de GRASS que producen una salida numérica ofrecen una bandera "-g" para facilitar el parseado de los resultados. Junto con la función "eval" de la shell se puede reducir el esfuerzo de usar la salida en el siguiente paso. El truco es que el signo de igual es considerado para asignar una variable en la shell:
# Ejemplo en el conjunto de datos North Carolina inmap=elevation outmap=some_result
Ejemplo para salida nomrnal de módulo:
g.region rast=$inmap r.info -r $inmap min=55.57879 max=156.3299
Usando esto en un script:
eval `r.info -r $inmap` r.mapcalc "$outmap = float($inmap) / $max"
Verificar:
r.info -r $outmap min=0.355522472489405 max=0.999999772928615
Mejores prácticas en la programación shell
Hay muchos libros sobre el tema, y el tema estará sujeto a preferencias personales, pero aquí hay algunos tips. Para parches enviados a GRASS, por favor siga las guías de código definidas en los archivos SUBMITTING
en el directorio principal del código fuente.
- trate de alcanzar 50% de comentarios, iniciando con el caracter # (ver arriba). De esta manera entenderá el script años después-
- añada un comentario inicial de qué es lo que hace el script
- estudie los scrips existentes, por ejemplo estos
Manejo de errores:
Un módulo que termina en un error fatal regresará un estatus no cero y salida (non-zero exit status), así que puede usar el comando con if
, ||
, &&
, etc., o probar el valor de $?
.
Insertando coordenadas en un módulo ráster a partir de un mapa vectorial de puntos
Algunos módulos ráster tienen la opción coordinates=
, pero no tienen la opción para seleccionarlas a partir de un mapa vectorial de puntos. El siguiente ejemplo se refiere al módulo r.viewshed.
Primero, debe tener un mapa vectorial con las coordenadas en la tabla de atributos; si no es así, añádalas con v.db.addcolumn y v.to.db.
Ejemplo 1: r.viewshed - seleccionando un solo punto a partir de un mapa vectorial
#!/bin/bash
# Autor: Marco Curreli
# Uso: sh myviewshed.sh cat
# "cat" es la categoría del punto del mapa vectorial
VECT=myvector
ARG=1
E_ERR_ARG=65
if [ $# -ne "$ARG" ]
### Verifica el número de argumentos ###
then
echo "Usage: $0 cat"
exit $E_ERR_ARG
fi
# coordenadas del punto
COR=$(v.db.select -c map=$VECT columns=x,y separator=, where="cat = $1")
r.viewshed --verbose -c in=dtm out=visib_$1 coordinate=$COR obs_elev=2.75 memory=3000 stream_dir=tmp
Ejemplo 2: r.viewshed - procesamiento en bloque para seleccionar puntos de un mapa vectorial
#!/bin/bash
# Autor: Marco Curreli
# Uso: sh myviewshed_batch.sh cat1,cat2[,cat3,...] [cat3..catN]
# "cat" es la categoría del punto del mapa vectorial
# ejemplo: to selecting cats 1 3 5 6 7
# sh myviewshed_batch.sh 1,3 5..7
VECT=myvector
CAT1=$(
for index in $(eval echo {$1})
do
echo -n "$index "
done
echo
)
CAT2=$(
for index in $(eval echo {$2})
do
echo -n "$index "
done
echo
)
ARG=1
E_ERR_ARG=65
if [ $# -lt "$ARG" ]
then
echo "Uso: $0 cat1,cat2[,cat3,...] [cat3..catN]
se debe especificar al menos un argumento"
exit $E_ERR_ARG
fi
# a trabajar con uno o dos argumentos
if [[ -n $2 ]]
then
CATS=$(echo $CAT1 $CAT2)
else
CATS=$(echo $CAT1)
fi
echo categories: $CATS
# lista de categorías con sus coordenadas
for i in $CATS
do
v.db.select -c map=$VECT columns=cat,x,y separator=, where="cat = $i" >> ${VECT}_coord.csv
done
PTI=$(echo $(cat ${VECT}_coord.csv))
for p in $PTI
do
set -- $p
#coordenadas
CORD=$( echo $p | gawk -F "," '{print $2","$3}')
#categoría
CAT=$( echo $p | gawk -F "," '{print $1}')
r.viewshed --verbose --overwrite in=dtm out=visib_$CAT coordinate=$CORD obs_elev=2.75 memory=1500 stream_dir=tmp
done
rm ${VECT}_coord.csv