Archivo

Entradas Etiquetadas ‘opciones’

Crear un archivo PHP que sólo contenga un array (desde un programa PHP)

Domingo, 9 de Enero de 2011 Gaspar Fernández Sin comentarios

Aunque puede parecer redundante, pero es una idea curiosa. Sobre todo cuando creamos un sitio web con muchas opciones. Tenemos varias opciones:

  • Guardarlas en base de datos. Con lo cual cada página que carguemos tiene que hacer una petición, y si hay muchas visitas podemos saturar el sistema. Además una petición es una tarea un poco lenta
  • Guardarlas en un archivo de texto. Por lo que tendremos que hacer un programa que lea el fichero y lo interprete. Puede llegar a ser lento si el formato de nuestro archivo es complicado.
  • Guardarlas en un fichero binario. Los problemas son parecidos a los del fichero de texto, aunque a lo mejor ahorramos algo en sintaxis al representar todo en bloques; pero si tenemos un problema podemos tardar mucho tiempo depurando y leyendo el fichero de configuración con un editor hexadecimal.
  • Archivo de texto con el array serializado (serialize()) y des-serializarlo (unserialize()) cuando vayamos a leer… Aunque no tengo claro cuánto tiempo invierten serialize() / unserialize(), pero supongo que más tiempo que una lectura simple de un array.
  • Crear un archivo PHP que contenga la configuración. Es lo más rápido ya que no tenemos que crear texto que interprete y se lee de forma nativa (hay que tener en cuenta que PHP es un lenguaje interpretado, sólo tiene que interpretar el código y no un lector que interprete la configuración como en los casos anteriores).

Vamos con este último. Estas rutinas las creé con esa idea en mente. Lo que hago es insertar un array en un archivo PHP, que luego leeré desde el programa con include()/require()/etc… y si tenemos que guardar la configuración, podemos utilizar esta función array_to_phpcode():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php

function var2php(&$var)
{
  if (is_numeric($var))
    $o=$var;
  else
    $o='\''.addslashes($var).'\'';

  return $o;
}

function array2php(&$array)
{
  $o='';
  if (is_array($array))
    {
      $o.=' array (';
      foreach ($array as $key=>$value)
    {
      $o.=var2php($key).' => '.array2php($value).",\n";
    }
      $o.=')';
    }
  else
    $o.=var2php($array);
  return $o;
}

/**
******************************************************************
* @brief Crea código PHP con un array como contenido
*
* @param $array    Array a insertar
* @param $phpvar   Variable PHP donde vamos a asignarlo
* @param $precode  Código PHP a incluir antes
* @param $postcode Código PHP a incluir después
*
* @return Código PHP
*
******************************************************************/

function array_to_phpcode(&$array, $phpvar, $precode, $postcode, $comment=false)
{
  $o ="<?php\n/* Fichero generado automáticamente por LYB el ".date("Ymd")." a las ".date("H:i").
    " */\n".$comment."\n\n".$precode."\n\n/* Array a incluir */\n";
  $o.=$phpvar.' = '.array2php($array).';';
  $o.="\n/* Información incluida */\n".$postcode."\n?>";

  return $o;
    }

$array=array('user' => 'Gaspy',
         'blog' => 'Poesía Binaria',
         'URL'  => 'http://totaki.com/poesiabinaria/'
         );

echo array_to_phpcode($array, 'usuario', "echo \"Hola Mundo\";", "/* DESPUÉS OTRO COMENTARIO */", "/* COMENTARIO INICIAL */");
?>

Aunque a la hora de salvar la información sea poco óptimo (ya que machacamos el archivo entero con contenidos nuevos cuando tal vez sólo cambia un elemento), pero la lectura de las opciones será muy rápida (y es lo que nos interesa porque tendremos que hacerlo a cada página que se cargue). De todas formas, siempre podemos desarrollar una nueva versión que busque las diferencias y sea capaz de ubicarlas en el archivo y sustituirlas, pero seguramente nos de un código bastante más lento.

Uso de llaves en BASH

Sábado, 15 de Mayo de 2010 Gaspar Fernández 1 comentario

llaves
Leo en el blog de Thalskarth (proveniente de Tux Files, que a su vez venía de Slice of Linux) un truco para hacer copias de seguridad de un archivo con bash de la siguiente forma:

cp archivo{,.bk}

Lo que hacemos es parecido a escribir esto otro:

cp archivo archivo.bk

Por lo que podemos intuir fácilmente para qué valen las llaves en este contexto: replicar alternativas. Es decir escribiremos lo que hay antes de la llave, y lo terminaremos con cada una de las opciones de dentro de las llaves que están separadas por comas. Y lo más fácil para entender esto es utilizar echo.
Probaremos lo siguiente:

$ echo “Voy a pintar mi casa de “{verde,azul,rojo,amarillo}
Voy a pintar mi casa de verde Voy a pintar mi casa de azul Voy a pintar mi casa de rojo Voy a pintar mi casa de amarillo

Bien, el mensaje se replica con un espacio entre réplicas. Podemos ahora probar algo más:

$ echo -e “Voy a pintar mi casa de “{verde,azul,rojo,amarillo}”.\n”
Voy a pintar mi casa de verde.
Voy a pintar mi casa de azul.
Voy a pintar mi casa de rojo.
Voy a pintar mi casa de amarillo.

Además, podemos ver que la llave no tiene por qué estar al final del parámetro, podemos ponerla en mitad y sigue funcionando. Hay un espacio al principio de la línea, como mencioné antes, las frases irán separadas por un espacio (es normal, las llaves nos sirven para introducir nuevos parámetros). Podremos solucionarlo con \b (backspace).

echo -e “\bVoy a pintar mi casa de “{verde,azul,rojo,amarillo}”.\n”
Voy a pintar mi casa de verde.
Voy a pintar mi casa de azul.
Voy a pintar mi casa de rojo.
Voy a pintar mi casa de amarillo.

Antes de nada un apunte, no debemos dejar espacios dentro de las llaves, ni entre las comas, ni dentro de cada opción, no olvidemos que son parámetros, aunque sí que podríamos poner un espacio si éste va entre comillas (igual que ocurre con los parámetros).

Crear PDFs

Y a partir de aquí, sólo necesitamos imaginación, por ejemplo podemos ver cómo lo usamos para crear un pdf con imágenes en jpeg (de una carpeta llamadas test-N.jpg). Lo creamos con ImageMagick y sólo queremos de la 1 a la 12:

$ convert test-{?.,10.,11.,12.}jpg todos.pdf

Aunque hay un método mejor, {} (las llaves) soportan rangos, por lo que podemos hacer:

$ convert test-{1..12}.jpg todos.pdf

Comprimir directorios

Podemos, por ejemplo crear un archivo comprimido de un directorio con el mismo nombre de la siguiente manera:

$ tar cvjf test{.tar.bz2,/}

como sustitución a:

$ tar cvjf test.tar.bz2 test/

Diferencias

Encontrar la diferencia de un archivo con su backup (suponemos que el backup es el mismo nombre terminado en ~ (tilde de la ñ):

$ diff test{,~}

O para diferencias rutas (recordemos que podemos poner llaves entre parámetros:

$ diff ~/proyectos/www/{proyecto1,proyecto2}/www/lib/my_lib.h

Que es lo mismo que:

$ diff ~/proyectos/www/proyecto1/www/lib/my_lib.h ~/proyectos/www/proyecto2/www/lib/my_lib.h

Lectura de datos en scripts

Para leer desde la entrada estandar tenemos read, y si queremos introducir cada palabra en una variable podemos usar read palabra1 palabra2 palabra3, y si queremos que estas variables tengan un prefijo común:

$ read palabra{A,B,C}

Combinaciones y juegos

Vamos a hacer múltiples sumas con bc:

$ echo -e {1..4}”+”{4..1}”\n” | bc

Esto pondrá en pantalla el resultado de: 1+4, 1+3, 1+2, 1+1, …, 4+3, 4+2, 4+1.
Con esto vemos que los rangos no sólo van en incremento sino también en decremento.
Pero aún más si hacemos:

echo test{a..z}

Nos completará con testa testb testc…testx, testy, testz

Por último, un ejemplo más complicado, y que, aunque pocas veces nos sirva (más que nada por no acordarnos), ahí queda, llaves anidadas:

$ echo test-{1{10..12},3{9..1}}
test-110 test-111 test-112 test-39 test-38 test-37 test-36 test-35 test-34 test-33 test-32 test-31

Tenemos la posibilidad de introducir opciones dentro de otras opciones y todas se representarán seguidas. ¿Tal vez nos sirva alguna vez para crear un fichero de texto con datos de prueba? Para crear un archivo con temperaturas de varias ciudades:

$ echo -e “\b”{”Madrid 1″{1..4},”Barcelona 1″{3..5},”Malaga “{19..22},”Sevilla 2″{3..4}}”\n” > test

Esto creará un fichero llamado test con el siguiente contenido:

Madrid 11
Madrid 12
Madrid 13
Madrid 14
Barcelona 13
Barcelona 14
Barcelona 15
Malaga 19
Malaga 20
Malaga 21
Malaga 22
Sevilla 23
Sevilla 24

Foto: bohman (Flickr)

Desea continuar? [(S)i, (N)o, (M)e lo pienso]

Lunes, 25 de Mayo de 2009 blakeyed Sin comentarios

Es común en los programas de consola hacer preguntas al usuario y éste responda, pero sólo una de las opciones válidas, si no, volver a preguntarle hasta que nos diga un valor correcto.

Aquí os enseño un ejemplo sencillo de todo esto (utilizaré la función mygetch):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>

int mygetch(int echo)
{
    struct termios oldt, newt;
    int ch;

    /* Obtenemos atributos del terminal */
    tcgetattr( STDIN_FILENO, &oldt );
    newt = oldt;
    /* Eliminamos el modo canónico: caracteres especiales */
    newt.c_lflag &= ~ICANON;
    /* Eliminamos el echo a voluntad */
        if (!echo)
            newt.c_lflag &= ~ECHO;
    /* Definimos los nuevos atributos al terminal */
    tcsetattr( STDIN_FILENO, TCSANOW, &newt );
    ch = getchar();
    /* Ponemos los atributos como estaban al principio */
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
    return ch;
}

int get_option(char *texto, char *validas)
{
    int tecla;
    char *ok;
    do
        {
            /* Mostramos texto en pantalla */
            printf("%s: ", texto);
            /* Pedimos una tecla y la pasamos a mayúsculas, para no */
            /* hacer demasiadas comprobaciones luego */
            tecla=toupper(mygetch(1));
            /* strpbrk nos dirá si tecla es una de las válidas */
            ok=strpbrk((char*)&tecla, validas);
            /* strpbrk devuelve NULL si no ha encontrado tecla en validas */
            if (ok==NULL)
                printf("\n¡Opción incorrecta! Por favor seleccione una de estas: %s\n", validas);
        } while (ok==NULL);
    return tecla;
}

int main()
{
    int tecla;

    do
        {
            tecla=get_option("Desea continuar? [(S)i, (N)o, (M)e lo pienso]", "SNM");
            switch (tecla)
                {
                case 'S': printf("\nHas elegido continuar...\n");
                      break;
                case 'N': printf("\nSalir\n");
                      break;
                case 'M': printf("\nTe doy 5 segundos para pensártelo\n");
                      sleep(5);
                      break;
                }
        } while (tecla!='N');
    return 0;
}

Como vemos, sólo tenemos que llamar a la función get_option, pasarle las opciones válidas, y la función sólo nos va a devolver una de las opciones que le digamos.

Categories: C/C++, Linux Tags: , , ,

Visita otras webs de la red