Foros del Web » Programación para mayores de 30 ;) » Programación General »

busquedas... mostrar dos lineas...

Estas en el tema de busquedas... mostrar dos lineas... en el foro de Programación General en Foros del Web. hola, tengo un problemilla con un script. el caso es que me funciona correctamente, ya que me hace las busquedas, pero lo que quiero es ...
  #1 (permalink)  
Antiguo 23/06/2006, 03:51
 
Fecha de Ingreso: junio-2003
Mensajes: 122
Antigüedad: 20 años, 10 meses
Puntos: 0
busquedas... mostrar dos lineas...

hola,

tengo un problemilla con un script.
el caso es que me funciona correctamente, ya que me hace las busquedas, pero lo que quiero es que me muestre dos lineas completas.
El script busca en un fichero plano los campos parecidos a lo que introduzca, entonces, me gustaría que cuando encuentre algún campo me muestre los resultados pero cogiendo las dos lineas...

este es el script:

Código:
confirm()
{
  echo -en "$@"
  read ans
  ans=`echo $ans | tr '[a-z]' '[A-Z]'`
  if [ "$ans" == "Y" ]; then
    return 0
  else
    return 1
  fi
}

num_lines()
{
  grep -i "$@" $masFICHERO|wc -l| awk '{ print $1, $2, $3, $4 , $5 }'
}

find_lines()
{
  # Busca lineas de entrada $1
  res=-1
  if [ ! -z "$1 " ]; then
    grep -i "$@" $masFICHERO
    res=$?
  fi
  return $res
}

list_items()
{
  # Lista los resultados encontrados
  if [ "$#" -eq "0" ]; then
    echo -en "Buscar usuario: (en blanco muesta toda la lista): "
    read search
    if [ -z "$search" ]; then
      search="."
    fi
    echo
  else
    search="$@"
  fi
  find_lines "${search}" | while read i
  do
  echo "$i" | tr ':' '\t'
  done
  echo -en "Encontrados: "
  num_lines "$search"
}

alguien me puede decir, como hago para que me muestre las dos lineas..¿??

gracias.

takezo
  #2 (permalink)  
Antiguo 23/06/2006, 06:17
Avatar de monoswim
$moderador{'Esteban'}
 
Fecha de Ingreso: febrero-2002
Ubicación: Buenos Aires - Argentina
Mensajes: 8.762
Antigüedad: 22 años, 2 meses
Puntos: 90
Hola, primeroq ue nada quiero ver si entendí, tienes un buscador que busca en un fichero línea por línea, y tu quieres que si encuentra una lína devuelva esta más la línea siguiente ?

Otra cosa, no puedes colocar el script entero ? porque no veo donde abren el archivo y en que variable colocan su info...

Saludos
__________________
Esteban Quintana
  #3 (permalink)  
Antiguo 24/06/2006, 13:28
Colaborador
 
Fecha de Ingreso: mayo-2006
Ubicación: Valladolid
Mensajes: 524
Antigüedad: 18 años
Puntos: 11
¡Es normal que no se entienda nada! ¡No es Perl! ¡Es script shell!

¡Herejía, herejía!
  #4 (permalink)  
Antiguo 26/06/2006, 03:12
 
Fecha de Ingreso: junio-2003
Mensajes: 122
Antigüedad: 20 años, 10 meses
Puntos: 0
ok.

Disculpad,

paso todo el código...

Código:
# Global variables
film=/opt/etc/film/film.txt
export film

confirm()
{
  echo -en "$@"
  read ans
  ans=`echo $ans | tr '[a-z]' '[A-Z]'`
  if [ "$ans" == "Y" ]; then
    return 0
  else
    return 1
  fi
}

num_lines()
{
  grep -i "$@" $film|wc -l| awk '{ print $1 }'
}

find_lines()
{
  # Busca lineas de entrada $1
  res=-1
  if [ ! -z "$1" ]; then
    grep -i "$@" $film
    res=$?
  fi
  return $res
}

list_items()
{
  # Lista los resultados encontrados
  if [ "$#" -eq "0" ]; then
    echo -en "Buscar usuario: (en blanco muesta toda la lista): "
    read search
    if [ -z "$search" ]; then
      search="."
    fi
    echo
  else
    search="$@"
  fi
  find_lines "${search}" | while read i
  do
    echo "$i" | tr ':' '\t'
  done
  echo -en "Encontrados: "
  num_lines "$search"
}

add_item()
{
  echo
  echo
  echo
  echo "          NUEVA PELI"
  echo " COMPLETA TODOS LOS DATOS"
  echo "  - AÑO MES DIA DIRECTOR TIPO - "
  echo
  echo -en "Nombre: "
  read name
  find_lines "^${name}:"
  if [ `num_lines "^${name}:"` -ne "0" ]; then
    echo "Pelicula, $name ya existe en el fichero."
    return
  fi
  echo -en "Año: "
  read "ano"
  echo -en "Director: "
  read filmaker
  echo -en "Genero:"
  read genre
  echo -en "Calificacion:"
  read calification

  # Confirmacion
  echo "${name} AnoPelicula=${ano}
        ${calification}, ${filmaker}, ${genre}" >> $film
  echo
  echo
  echo -en "--> ALTA FILM"
  echo
  echo
}

locate_single_item()
{
  echo -en "Peli a buscar: "
  read search
  n=`num_lines "$search"`
  if [ -z "$n" ]; then
    n=0
  fi
  while [ "${n}" -ne "1" ]; do
    #list_items "$search"
    echo -en "${n} peli encontrada. Selecciona una "
    case "$n" in
      "0") echo "menos" ;;
      "*") echo "mas" ;;
    esac
    echo "especifica un patron de busqueda (q para volver al menu anterior): "
    read search
    if [ "$search" == "q" ]; then
      return 0
    fi
    n=`num_lines "$search"`
  done
  return `grep -in $search $film |cut -d":" -f1`
}

#remove_item()
#{
#  locate_single_item
#  search=`head -2 $film`
#  if [ -z "${search}" ]; then
#       return
#  fi
#  list_items "$search"
#  confirm "Borrar?"
#  if [ "$?" -eq "0" ]; then
#    grep -v "$search" $film > ${film}.tmp ; mv ${film}.tmp ${film}
#  else
#    echo "NO BORRADO"
#  fi
#}

edit_item()
{
  locate_single_item
  search=`head -$? $film | tail -1|tr ' ' '.'`
  if [ -z "${search}" ]; then
        return
  fi
  list_items "$search"
  thisline=`grep -i "$search" $film`
  oldname=`echo $thisline|cut -d"" -f1`
  oldano=`echo $thisline|cut -d"," -f2`
  oldfilmaker=`echo $thisline|cut -d"," -f3`
  oldcalification=`echo $thisline|cut -d"," -f4`
  oldgenre=`echo $thisline|cut -d"," -f5`

  echo "BUSCAR : $search"
  grep -v "$search" $film > ${film}.tmp ; mv ${film}.tmp ${film}
  echo -en "Pelicula [ $oldname ] "
  read name
  if [ -z "$name" ]; then
    name=$oldname
  fi
  find_lines "^${name}:"
  if [ `num_lines "^${name}:"` -ne "0" ]; then
    echo "La pelicula, $name esta en el fichero."
    return
  fi
  echo -en "ano [ $oldano ] "
  read ano
  if [ -z "$ano" ]; then
    ano=$oldano
  fi
  echo -en "Pelicula [ $oldfilmaker ] "
  read filmaker
  if [ -z "$filmaker" ]; then
    filmaker=$oldfilmaker
  fi
  echo "${name}:${ano}:${filmaker}" >> $film
}

Última edición por startwav; 26/06/2006 a las 06:03
  #5 (permalink)  
Antiguo 26/06/2006, 05:50
Avatar de monoswim
$moderador{'Esteban'}
 
Fecha de Ingreso: febrero-2002
Ubicación: Buenos Aires - Argentina
Mensajes: 8.762
Antigüedad: 22 años, 2 meses
Puntos: 90
Oye eso no está escrito en PERL...No se si alguien acá conocerá de script shell...

Saludos
__________________
Esteban Quintana
  #6 (permalink)  
Antiguo 26/06/2006, 05:52
 
Fecha de Ingreso: junio-2003
Mensajes: 122
Antigüedad: 20 años, 10 meses
Puntos: 0
cierto
  #7 (permalink)  
Antiguo 26/06/2006, 05:57
Colaborador
 
Fecha de Ingreso: mayo-2006
Ubicación: Valladolid
Mensajes: 524
Antigüedad: 18 años
Puntos: 11
¿Puedes poner un par de líneas del fichero /opt/etc/film/film.txt?
  #8 (permalink)  
Antiguo 26/06/2006, 06:02
 
Fecha de Ingreso: junio-2003
Mensajes: 122
Antigüedad: 20 años, 10 meses
Puntos: 0
todas las lineas del fichero vendrían a ser como esta:


Clerks AñoPelicula="2002"
Calificacion=7, Director=Smith, Genero=Independiente,
  #9 (permalink)  
Antiguo 26/06/2006, 16:10
Colaborador
 
Fecha de Ingreso: mayo-2006
Ubicación: Valladolid
Mensajes: 524
Antigüedad: 18 años
Puntos: 11
Supongamos que todo el fichero de películas es como dices: dos líneas en la cual la primera es el nombre de la película y su año y en la siguiente todo lo demás.
Es decir, los registros de cada película empiezan en línea impar y terminan en una línea par.

El problema que tienes es que de esta manera, organizado por varias líneas, el grep de la línea 27 no funciona mas que como tu dices: sólo saca las líneas que coinciden con el patrón buscado, pero no todo el registro.

Se solucionaría de un plumazo si toda la base de datos contuviera los registros, uno por línea.

Supongamos que no, que queremos que sigan siendo cada dos líneas. Es evidente entonces que hay que cambiar la función find_lines para que nos busque, además de las líneas que coinciden con lo buscado, aquellas líneas que son sus 'compañeras'.

Esta es la nueva versión de find_lines:
Código:
   22 find_lines()
   23 {
   24   # Busca lineas de entrada $1
   25   res=-1
   26   if [ ! -z "$1" ]; then
   27     perl -ne '
   28         BEGIN { $busca = shift; }
   29         if ( /$busca/ ) {
   30                 unless ( $. % 2 ) { # Si es par
   31                         print $linea_anterior;
   32                         print $_;
   33                 }
   34                 else {  # Si es impar
   35                         print $_;
   36                         $siguiente = <>;
   37                         print $siguiente;
   38                 }
   39         }
   40         $linea_anterior = $_;
   41     ' "$@" $film
   42     #grep -i "$@" $film
   43     res=$?
   44   fi
   45   return $res
   46 }
De la línea 27 a 41 ponemos un script en Perl y comentamos el grep en la línea 42, ya que no nos hace falta.

El funcionamiento del script es el siguiente:
27: Ejecutamos Perl con la opción -n (recorrer todo el fichero $film) y la -e (ejecutar el script puesto a continuación)
28: BEGIN se ejecutará sólo una vez, al principio. Lo que hace es leer el primer parámetro que le pasamos al script (línea 41) que es "$@", el argumento de búsqueda
29: Esta línea y las siguientes se ejecutan una vez por cada línea del fichero $film. Aquí comprobamos si la línea leída coincide con el patrón de búsqueda. Vamos, que funciona exáctamente igual que el grep anterior
30: Hemos encontrado una coincidencia. Vemos ahora si el número de línea actual ($.) es par o no. Hacemos el truco de sacar el módulo (%) de 2 y si el resultado es 0, entonces es par. Sino, es impar.
31: La línea con la coincidencia es par, luego estamos en la segunda parte de un registro. Necesitamos pintar primera la $linea_anterior, y luego la línea actual.
34: Si es impar...
35: estamos en la primera línea de un registro. Pintamos esa línea...
36: leemos una línea más del fichero...
37: y la pintamos.
40: Guardamos la línea procesada como $linea_anterior para el siguiente bucle, por si nos hace falta en la línea 31.
43: res se actualiza con el resultado de la ejecución del perl, exáctamente igual que si fuera el grep.

¡Y ya está!

Perl es multiusos
  #10 (permalink)  
Antiguo 05/07/2006, 03:39
 
Fecha de Ingreso: junio-2003
Mensajes: 122
Antigüedad: 20 años, 10 meses
Puntos: 0
Sonrisa

jferrero, muchas gracias por la ayuda, la verdad es que ha funcionado perfectamente, bueno , he tenido que colocar un poco las lineas de la bb.dd pero ha funcionado correctamente.... vamos, PERFECTO.!

Ahora tengo un pequeño problema...
modificar los campos de la bb.dd. tengo creado lo siguiente:

(tomado de código de arriba pego la opción editar entradas del fichero donde esta toda la info.)

...

Código:
....

edit_item()
{
  locate_single_item
  search=`head -$? $film | tail -1|tr ' ' '.'`
  if [ -z "${search}" ]; then
        return
  fi
  list_items "$search"
  thisline=`grep -i "$search" $film`
  oldname=`echo $thisline|cut -d"" -f1`
  oldano=`echo $thisline|cut -d"," -f2`
  oldfilmaker=`echo $thisline|cut -d"," -f3`
  oldcalification=`echo $thisline|cut -d"," -f4`
  oldgenre=`echo $thisline|cut -d"," -f5`

  echo "BUSCAR : $search"
  grep -v "$search" $film > ${film}.tmp ; mv ${film}.tmp ${film}
  echo -en "Pelicula [ $oldname ] "
  read name
  if [ -z "$name" ]; then
    name=$oldname
  fi
  find_lines "^${name}:"
  if [ `num_lines "^${name}:"` -ne "0" ]; then
    echo "La pelicula, $name esta en el fichero."
    return
  fi
  echo -en "ano [ $oldano ] "
  read ano
  if [ -z "$ano" ]; then
    ano=$oldano
  fi
  echo -en "Pelicula [ $oldfilmaker ] "
  read filmaker
  if [ -z "$filmaker" ]; then
    filmaker=$oldfilmaker
  fi
  echo "${name}:${ano}:${filmaker}" >> $film
}
el caso o problema es que no me reconoce bien la busqueda y luego los campos no los respeta... se come las cosas y no sustituye los campos correctamente.
me puedes echar una mano para que cuadre todo un poco más...¿???

en el fichero con la info. los campos vienen a quedar tal que así:

Clerks AñoPelicula="2002"
Calificacion=7, Director=Smith, Genero=Independiente

Siendo campos fijos:

AñoPelicula=
Calificacion=
Director=
Genero=

no sé si me he explicado correctamente... espero que sí.

gracias por la ayuda.!!!
  #11 (permalink)  
Antiguo 05/07/2006, 11:04
Colaborador
 
Fecha de Ingreso: mayo-2006
Ubicación: Valladolid
Mensajes: 524
Antigüedad: 18 años
Puntos: 11
Es que el problema es el mismo...

Después de la línea thisline=`grep -i "$search" $film` vienen una serie de 'cuts', y cada uno de ellos está intentando sacar cada uno de los campos de la base de datos. Y para eso, cada uno de ellos 'piensa' que la CADA LÍNEA del fichero es un ÚNICO REGISTRO. Saca el campo, 1, luego el 2, el 3, el 4 y el 5 y los guarda en oldname, oldano, oldfilmaker, oldcalification y oldgenre.

Te recomiendo que te dejes de romper la cabeza y conviertas la base de datos a una sola línea por registro, porque ESE es el formato que usa el programa (salvo en la función add_item, que, naturalmente, también está mal poque escribe los registros en varias líneas).

Si dices que no, que es necesario que esté en varias líneas...
yo aprendería Perl... sería más cómodo, corto y fácil de entender.
  #12 (permalink)  
Antiguo 05/07/2006, 12:10
 
Fecha de Ingreso: junio-2003
Mensajes: 122
Antigüedad: 20 años, 10 meses
Puntos: 0
qué web me recomiendas para emfrentarme concretamente a este nuevo problema...¿?? que código perl para solucionarlo...¿?

el caso es, que efectivamente, ha de estar en dos lineas separadas... es una movida, pero tiene que ser así...


gracias.!
  #13 (permalink)  
Antiguo 05/07/2006, 16:25
Colaborador
 
Fecha de Ingreso: mayo-2006
Ubicación: Valladolid
Mensajes: 524
Antigüedad: 18 años
Puntos: 11
No entiendo porqué no ha de ser en una línea. La diferencia en la longitud del programa puede ser exactamente ese: si el registro ocupa dos líneas, es muy posible que el programa en Perl ocupe el doble que si sólo ocupara una...

No conozco un código específico para esto, pero con el módulo Tie::File se debería poder resolver muy rápidamente.

Si necesitas que sean dos líneas... pues ha hacer el programa...
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 23:52.