Discussion:
Comportamiento extraño (al menos a mi me lo parece) en Bash
(demasiado antiguo para responder)
Bypper
2009-11-13 09:03:21 UTC
Permalink
Buenas:

Tengo 2 ficheros de texto, ambos con un listado de ficheros con el
nombre y el tamaño:

$ ls -l /tmp/comproba_*
-rw-r--r-- 1 I0775 users 56 nov 12 13:50 /tmp/comproba_antes
-rw-r--r-- 1 I0775 users 56 nov 12 15:12
/tmp/comproba_despues

$ cat /tmp/comproba_antes

.. 4096
comproba.sh 425
. 4096
.comproba.sh.swp 12288

$ cat /tmp/comproba_despues

.. 4096
.comproba.sh.swp 12288
comproba.sh 531
. 4096

Y luego un script que simplemente comprueba cada fichero del
"comproba_antes" a ver si esta en el "comproba_despues", pero tiene un
comportamiento extraño que no entiendo.

El script es el siguiente:
..................................................
#!/bin/bash
# defino los 2 ficheros...
ANT='/tmp/comproba_antes'
DES='/tmp/comproba_despues'
# compruebo parametro de entrada...
[[ $# -ne 1 ]] && exit 1
# funcion de grepeo sobre el 2º fichero...
aversiesta(){
grep $1 $DES
}
comparativa(){
# procesamos todas las lineas del fichero 1...
cat $ANT | while read L
do
# definimos variable con el campo 1: el nombre...
fich=$(echo $L | cut -f1 -d' ')
# si no es '.' ni '..' nos vale ...
[[ $fich = '.' ]] || [[ $fich = '..' ]] || echo $fich
done
}
comparativa
..................................................
Aqui la salida es correcta, sale el nombre del fichero, y la variable
$fich extrae el valor sin problemas.

$ bash comproba.sh2 .

comproba.sh
.comproba.sh.swp


Pero luego, si hago la modificación siguiente:

comento esta linea:
[[ $fich = '.' ]] || [[ $fich = '..' ]] || echo $fich
y descomento la siguiente (que está comentada ahora)
[[ $fich = '.' ]] || [[ $fich = '..' ]] || aversiesta $fich

con la intención de llamar a la función "aversiesta" con la variable
$fich como parametro de entrada, entonces esta variable ya no coge valor
alguno, observad:

$ bash -x comproba.sh2 .
+ ANT=/tmp/comproba_antes
+ DES=/tmp/comproba_despues
+ [[ 1 -ne 1 ]]
+ comparativa
+ cat /tmp/comproba_antes
+ read L
++ echo
++ cut -f1 '-d '
+ fich=
+ [[ '' = \. ]]
+ [[ '' = \.\. ]]
+ aversiesta
+ grep /tmp/comproba_despues
+ read L
$
$

Es decir, todavia no ha llegado a procesar la linea que hemos añadido, y
la variable definida anteriormente esta ahora vacia. !!!!

no se, supongo que algo se me escapa, pero no veo el que ...

No se si me he explicado bien, cualquier duda me comentais...

saludos,
Gonzalo Pérez de Olaguer Córdoba
2009-11-13 11:34:47 UTC
Permalink
Post by Bypper
Es decir, todavia no ha llegado a procesar la linea que hemos añadido, y
la variable definida anteriormente esta ahora vacia. !!!!
Antes también salían dos líneas vacías, una al principio y otra al final.
Parece que los ficheros /tmp/comproba_{antes,despues} contienen líneas
en blanco.

Por lo tanto ``grep $1 $DES'' se convierte en ``grep /tmp/comproba_despues´´.
Observa que a grep le falta un parámetro. grep interpreta el argumento como
el PATRÓN de búsqueda, y lee los datos a filtrar de stdin. O sea, todo lo que
queda del ``cat $ANT''. No encuentra nada que coincida con /tmp/comproba_antes
y devuelve 1. Luego se ejecuta el último read L, que devuelve false porque
toda la entrada se la ha chupado el grep.

Una solución, que te dará resultados curiosos (pruébala) es simplemente meter
el argumento a grep entre comillas: ``grep "$1" $DES''.

Pero lo mejor es filtrar: ``[[ -n "$1" ]] && grep "$1" "$DES"''. Siempre es bueno
en bash encerrar los argumentos entre comillas, para evitar que los argumentos
desaparezcan o se conviertan en varios argumentos adicionales (si hay blancos por
enmedio).

Verás que algunas líneas de la salida están duplicadas (porque comproba.sh
también vale para .comproba.sh.swp). Si quieres evitar eso complica la
expresión regular: ``grep "^$1 " "$DES"''.

Saludos,
Gonzalo.
--
Gonzalo Pérez de Olaguer Córdoba <***@iies.es> --- www.gpoc.es
PGP key 2861C704 --- F206 5671 6789 425D 111C 1302 214F 1934 2861 C704
Bypper
2009-11-14 11:25:18 UTC
Permalink
Gonzalo Pérez de Olaguer Córdoba escribió:
...
Post by Gonzalo Pérez de Olaguer Córdoba
Una solución, que te dará resultados curiosos (pruébala) es simplemente meter
el argumento a grep entre comillas: ``grep "$1" $DES''.
Pero lo mejor es filtrar: ``[[ -n "$1" ]] && grep "$1" "$DES"''. Siempre es bueno
en bash encerrar los argumentos entre comillas, para evitar que los argumentos
desaparezcan o se conviertan en varios argumentos adicionales (si hay blancos por
enmedio).
...

Efectivamente Gonzalo, en realidad es una práctica que suelo realizar
habitualmente, pero en este caso la verdad, no lo he asociado para nada
y no he llegado a plantearmelo.

Muchas gracias !!

Loading...