Rhynoceros
Linux, science, and other cool stuff

Construir expresiones en Powershell

Ayer, de chiripa, averigüe cómo hacer algo en Powershell que, si bien no es particularmente impresionante, sí está bien porque indica lo que se puede hacer con Powershell en Windows y, además, porque me pareció bonito.

Ayer me di cuenta de que si escribo lo siguiente en el shell:

cd (dir env:|where {$_.name -eq “Path”}).value.split(“;”)[-1]

Powershell cambia el directorio actual a:

C:\Windows\System32\WindowsPowerShell\v1.0

Bastante incomprensible, ¿no? Bueno, vayamos por partes.

La base del comando que he mostrado es:

dir env:

Esta instrucción sirve para mostrar la información que proporcionar el Provider de Environment. Este provider en Powershell nos permite ver las variables de entorno de Windows. Entre ellas están el nombre del usuario actual, las rutas de las carpetas especiales, el path, etc.

Si añadimos lo siguiente al comando:

dir env:|where {$_.name -eq “Path”}

Veremos solamente el path del usuario actual:

Name: Path
Value: %SystemRoot%\system32\WindowsPowerShell\v1.0\;C:\Windows\system32;C:\Windows;C:\Windo…

Dir nos devuelve un grupo de objetos (generalmente objetos que representan ficheros, aunque en este caso son objetos que representan variables de entorno). El carácter | se usa igual que en Unix para pasar el resultado de un comando a otros comando usando una pipa.

En este caso le pasamos el resultado de dir env: a where, y a where le decimos que de los objetos que ha recibido nos devuelva sólo los objetos cuya propiedad name tenga el valor de “Path”. Esto nos devuelve un sólo objetos que representa la variable de estado Path.

Ahora modificamos el comando:

(dir env:|where {$_.name -eq “Path”}).value

Esto nos devuelve:

%SystemRoot%\system32\WindowsPowerShell\v1.0\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\

Lo que hemos hecho aquí es usar el dot notation de Powershell. Los objetos que manejamos en Powershell tienen propiedades y métodos (qué propiedades y qué métodos en concreto dependen del objeto en sí), y podemos acceder a esas propiedades y métodos poniendo un punto al final del nombre del objeto y luego escribiendo el nombre de la propiedad o método que queremos.

Por ejemplo, si creamos una variable que contiene una cadena:

$a = “Cadena”

Las variables que contienen cadenas tiene propiedades a las que podemos acceder mediante el punto:

$a.length
6

Y métodos también:

$a.toupper()
CADENA

¿Qué tiene esto que ver con el comando original? El dot notation se suele usar con variables, pero no es su único uso permitido. También podemos usar el dot notation para acceder a métodos y propiedades de objetos referenciados de otras formas. En nuestro ejemplo usamos el dot notation directamente sobre el comando dir env:|where {$_.name -eq “Path”} para acceder a una de las propiedades del objeto creado por ese comando.

Lo que hacemos en este caso es envolver el comando en sí entre paréntesis, y de esa forma ya podemos usar el dot notation. Volviendo al ejemplo de la cadena:

(“cadena”).length
6
(“cadena”).toupper()
CADENA

Por tanto, ahora lo que obtenemos es el valor de la propiedad value de la variable de entorno llamada Path. Este valor es una cadena que contiene todas las carpetas que están en el path, separadas con punto y coma. Tal como están no sirven para mucho, así que vamos a usar el dot notation otra vez para separarlas:

(dir env:|where {$_.name -eq “Path”}).value.split(“;”)

Y eso nos da:

%SystemRoot%\system32\WindowsPowerShell\v1.0\ C:\Windows\system32 C:\Windows C:\Windows\System32\Wbem C:\Windows\System32\WindowsPowerShell\v1.0\

Las cadenas en Powershell tienen un método llamado split, que separa una sola cadena en varias usando un carácter que le proporcionamos como separador. Cuando usamos este método Powershell parte la cadena inicial y guarda los resultados en un array. El resultado mostrado en pantalla es un array: Powershell muestra los arrays en pantalla poniendo cada valor del array en una linea, del primero al último.

Podemos acceder a un elemento específico dentro de un array usando la notación []. Por ejemplo:

$b = @(“a”,”b”,”c”)

Creará un array llamado b que contiene las cadenas “a”, “b” y “c”. Podemos ver el array:

$b
a
b
c

Si lo que queremos es ver el primer elemento del array:

$b[0]
a

Powershell numera los elementos de los arrays empezando por 0. ¿Pero eso no es todo! ¿Qué pasa si queremos ver el último elemento del array? Podemos pedirle a Powershell que nos muestre el elemento con ese número:

$b[2]
c

¿Y si no sabemos cuántos elementos hay en el array? Podemos contar los elementos primero:

$b.count
3

Y luego buscar el elemento con ese número:

$b[$b.count-1]
c

Funciona, pero es un poco feo, ¿no? Powershell opina lo mismo, por eso nos permite hacer lo siguiente:

$b[-1]
c

Si le pedimos que nos muestre el elemento número -1 de una array, nos mostrará el primer elemento empezando desde el final.

Si volvemos al comando original, vemos que al escribir:

(dir env:|where {$_.name -eq “Path”}).value.split(“;”)[-1]

Powershell nos devolverá:

C:\Windows\System32\WindowsPowerShell\v1.0\

Que es la última ruta dentro de la variable de estado Path.

Ahora, como queremos ir asa ruta, usamos el comando cd:

cd (dir env:|where {$_.name -eq “Path”}).value.split(“;”)[-1]

Y Powershell cambia el directorio actual:

PS C:\Windows\System32\WindowsPowerShell\v1.0>

Y así podemos decirle a Powershell que cambie la ruta actual a la última carpeta contenida en el Path del usuario actual, en una sola linea. Este ejemplo en particular no es lo más útil del mundo, pero es un buen ejemplo del uso de pipas y del dot-notation en Powershell, y un portento de lo que se puede llegar a hacer.

A todo esto, se puede usar otra instrucción más simple para hacer lo mismo:

cd $env:path.split(“;”)[-1]

La variable $env:path es el mismo objeto que se obtiene con el comando (dir env:|where {$_.name -eq “Path”}).value. Esa variable viene ya pre-definida en Powershell, y nos permite acceder a ese mismo objeto sin necesidad de construir una expresión con pipas.

Written by valhar2000

January 11th, 2012 at 11:38 am

11 Comments

Posted in Uncategorized

SSH Command line tricks

Espectacular lista de trucos para SSH:
http://blog.urfix.com/25-ssh-commands-tricks/

Written by j_melis

December 8th, 2010 at 10:30 am

14 Comments

Posted in Linux

Enviar STDOUT a varios procesos

Hace poco me encontré con el problema de que tenía que clonar 1 disco 3 veces. Para ello enchufo los 4 discos en un servidor, arranco un livecd y solía ejecutar:

dd if=/dev/sda of=/dev/sdb
[~1h después]
dd if=/dev/sda of=/dev/sdc & dd if=/dev/sdb of=/dev/sdd

Al cabo de un tiempo descubrí en un artículo que podía redirigir el STDOUT de un proceso al STDIN de varios, reduciendo el tiempo total a la mitad!

dd if=/dev/sda|tee >(dd of=/dev/sdb) >(dd of=/dev/sdc)|dd of=/dev/sdd

Written by j_melis

November 16th, 2010 at 4:17 pm

15 Comments

Posted in Linux

Continuar con un proceso en el background

Sucede muy a menudo que ejecutamos un comando sin pensárnoslo mucho para luego darnos cuenta de que va a tardar mucho. En esas circunstancias todos sabemos cómo detener su ejecución (CTRL+C) o incluso cómo mandarlo al background (CTRL+z). Lo que yo no sabía, que descubrí hace poco era cómo continuar con el proceso en el background.

Lo primero que hay que hacer es suspender el proceso con CTRL+Z. Esta orden nos devolverá el job id del comando (en nuestro caso ‘3′):

$ ./slow_program.sh
^Z
[3]+ Stopped ./slow_program.sh
$

Para continuar con el proceso debemos utilizar el shell built-in ‘bg’ y hacemos referencia al job:

$ bg %3
[3]+ ./slow_program.sh &
$

Por supuesto otra alternativa es usar GNU Screen.

Written by j_melis

November 9th, 2010 at 5:36 pm

16 Comments

Posted in Linux

Procesando imágenes con ImageMagick

ImageMagick es uno de los programas más extraordinarios que conozco. Se trata de unas librerías (accesibles muy cómodamente a través de comandos de la CLI) que permiten el procesamiento de imágenes.

Hace unos días estuve de viaje y me llevé una camarita compacta: Canon Ixus 950 IS. La cámara en sí no está mal, pero no es una maravilla tampoco. Hay una serie de filtros que me gusta aplicar a las imágenes para mejorar la calidad:

  • Incremento (leve) de saturación
  • Incremento (leve) de contraste
  • Filtro de un-sharp

Por supuesto estos filtros no se deben de aplicar sobre todas las fotos, siempre hay un trabajo manual en cada foto. Pero a grandes rasgos mejora la calidad de la mayoría de las fotos.

ImageMagick dispone de unas guías de refencia muy buenas. Junto con eso y otros recursos online [1] he obtenido un comando genérico que produce un resultado bastante satisfactorio:

mogrify -verbose -brightness-contrast +0x+5 -modulate 100,120 -unsharp 1.5x1.2+1.0+0.10 *


[1] http://redskiesatnight.com/2005/04/06/sharpening-using-image-magick/

Written by j_melis

November 9th, 2010 at 1:45 pm

15 Comments

Posted in Linux

Retomando el blog…

La verdad es que no sé por qué he dejado morir este blog. Sucede muy a menudo que hago algo (en Linux generalmente) y que tiempo después trato de volver a hacerlo. Al haber pasado mucho tiempo me olvido y tengo que invertir la misma cantidad de tiempo en reaprender lo que alguna vez hice.

De forma que quiero retomar el blog para ir apuntando de nuevo cosas que voy aprendiendo, y darle un formato de Cookbook, que siempre es lo que he echado de menos.

Un truco que utilizo desde hace un tiempo es subir las líneas del bash_history para no perder los comandos habitualmente:

export HISTFILESIZE=100000
export HISTSIZE=100000

Ahora mismo mi ~/.bash_history va por 38000 entradas y no noto caída de eficiencia. Una pasada.

Written by j_melis

November 9th, 2010 at 1:25 pm

15 Comments

Posted in Linux

Amigo invisible

Intentando hacer un programita que cogiera una pequeña lista de nombres y los relacionara aleatoriamente, con idea de usarlo como generador automático de combinación de amigos invisibles, me di cuenta de que había muchos pequeños problemitas que no eran tan fáciles de resolver. Hablando con uno de mis compañeros de curro que tenía todos estos temas muy claros, me contó una serie de conceptos que se podían aplicar a estos problemas para resolverlos.

El algoritmo más obvio para hacer estas correspondencias es iterar sobre cada una de las personas e ir escogiendo aleatoriamente una persona entre las que quedan disponibles. Sin embargo este algoritmo falla. Os pongo un ejemplo de un caso de fallo: Supongamos 5 personas: “A”, “B”, “C”, “D” y “E”.

  • Empezamos por “A”, escogemos una persona aleatoriamente entre “B”, “C”, “D” y “E”: le toca “B”.
  • Para “B” escogemos una persona aleatoriamente entre “A”, “C”, “D” y “E”: le toca “C”.
  • Para “C” las opciones libres son “A”, “D”, y “E”: le toca “D”.
  • “D” tiene como posibilidades “A” o “E”, supongamos que le toca “A”.
  • Falta por asignarle una pareja a “E” pero ya no queda ninguna libre, así que a “E” le tendría que tocar a sí mismo.

Gráficamente:
5 personas

Teniendo esto en cuenta, lo que hice en mi primera versión generadora de parejas, es generar tantas veces como sea necesario hasta que no se produzca este error: código.

Por supuesto eso no es una solución satisfactoria, una técnica mucho mejor sería el algoritmo del encadenamiento, ordenando los elementos de forma aleatoria y que a cada uno le corresponda el siguiente, y si es el último le toca el primero:
5 personas
Sin embargo este sistema presenta el problema de que nunca se van a producir parejas directas del tipo “A” <-> “B” que en algún caso podría resultar conveniente.

En este momento entran en juego las particiones.

La partición de un número son las distintas posibles combinaciones para representarlo como adiciones de números inferiores o iguales a él:

  • 3: 1+1+1, 1+2, 3
  • 4: 1+1+1+1, 1+1+2, 1+3, 2+2, 4
  • 5: 1+1+1+1+1, 1+1+1+2, 1+1+3, 1+4, 2+3, 5

Podemos traducir esto a nuestro problema. Si cogemos el número de personas de nuestro problema, por ejemplo 5, escogemos una partición determinada, por ejemplo 2+3, y lo dividimos en tantos grupos como elementos tiene la partición, podemos realizar un amigo invisible para cada uno de estos subgrupos, mediante al algoritmo de encadenamiento expuesto antes.

Aplicándolo al ejemplo anterior, “A” y “B” pertenecen al subgrupo 2 y “C”, “D”, y “E” al subgrupo 3 (obtenidos por ser una partición 5 = 2 + 3).

5 personas

Si en lugar de haber escogido la partición 2 + 3, hubiéramos escogido 1 + 4, o cualquier otra partición en el que figure el número 1, ese subgrupo (una persona) se correspondería a sí mismo. Por tanto, a la hora de hacer correspondencias debemos de ignorar todas aquellas particiones en las que figure el número 1. En el caso del número 5 nos quedaríamos por tanto, sólo con 2+3 y 5.

Hacer un programa teniendo esto en cuenta es fácil. Suponemos que tenemos como input una lista de N nombres:

  1. Reordenamos la lista aleatoriamente
  2. Encontramos todas las particiones de N en las que no figure el número 1
  3. Escogemos, de las anteriores particiones una aleatoriamente
  4. Mapeamos la lista de nombres a los subgrupos creados a partir de la partición escogida
  5. Para cada subgrupo aplicamos el algoritmo de encadenamiento

Siguiendo este modelo he escrito este programa. Output de una ejecución:

$ ./amigo_invisible.py A B C D E
Partition: [2, 3]
Shuffled Names: ['D', 'C', 'B', 'E', 'A']
-------------
element partition: 2
names subgroup ['D', 'C']
C => D
D => C
-------------
element partition: 3
names subgroup ['B', 'E', 'A']
A => B
B => E
E => A

Couples
A => B
C => D
B => E
E => A
D => C

A la hora de elegir la partición he aplicado un sistema aleatorio sin más, se le podría haber dado peso a ciertas particiones para que algunas salgan con más frecuencia.

Written by j_melis

December 3rd, 2009 at 12:35 am

17 Comments

Posted in Linux

HPC via GPGPU

El otro día leyendo la siguiente noticia me pregunté que pasará si se empiezan a adoptar soluciones basadas en GPUs en los clusters dedicados a la investigación.

http://www.hpcwire.com/topic/systems/Julich_Supercomputing_Center_Keeps_Germany_on_the_Cutting_Edge_of_HPC-48781997.html

Es interesante que Europa no pierda el tren en cuanto a centros de computación, son vitales para el desarrollo científico y la nueva vía para avanzar en cualquier campo de la ciencia, aparte del viejo método científico, cada vez cobra más importancia la simulación de todo tipo de experimentos mediante superordenadores. Experimentos que no se podrían realizar de otra manera y que luego se contrasten con las predicciones de las teorías.

Si se echa un vistazo al TOP500, dentro de los 10 superordenadores con mayor rendimiento solo dos son europeos, el resto estadounidenses.

http://www.top500.org/lists/2009/06

Espero que se explore la vía que abren las nuevas GPUs, con rendimientos en coma flotante decenas de veces superiores a los de las CPUs más potentes. Hasta ahora NVIDIA ofrecía soluciones enracables de 2 a 4TFLOPS en 1U (http://www.beyond3d.com/content/articles/106), la mayor pega era la poca flexibilidad de esas GPUs frente a CPUs de proposito general y la falta de memoria ECC.

Pronto saldrá al mercado la nueva serie de GPUs de NVIDIA directamente dedicadas al HPC, la serie Fermi (http://www.nvidia.com/object/fermi_architecture.html), con memoria ECC, cálculo de doble precisión, soporte para lenguajes de programación más convencionales como C++ o Fortran aparte de CUDA y OpenCL. Es de esperar que el rendimiento se acerque a los 10TFLOPS/1U (para calculos de precision simple).

Ya se ha comprobado en proyectos de computación distribuida como folding@home (8 PFLOP/s) que cierto tipo de cálculos científicos se ejecuta mucho más rapido en GPUs, pulverizando el resultado de las CPUs y dejando muy atras en rendimiento al mayor centro de computación no distribuida, IBM Roadrunner (1,1 PFLOP/s).

Lo que me pregunto es si las enormes prestaciones de éstas nuevas GPUs dedicadas a clusters HPC serían utiles a nivel empresarial en el manejo de bases de datos, cargas batch, tratamiento masivo de datos en definitiva o si por el contrario serían ineficaces en ese tipo de funciones, dependientes de un flujo I/O brutal más que de capacidad de procesamiento en procesador y memoria.

Written by r.daneelolivaw

November 25th, 2009 at 2:45 am

19 Comments

IE 9 va a tener aceleración de GPU

Aunque no sé si va a tener filtrado anisotrópico, o modelos animados con más de 150.000 polígonos: http://www.fudzilla.com/content/view/16528/1/

A ver si se va poniendo de moda hacer esto, porque vendría bien que más programas aprovechansen la GPU para hacer trabajos intensivos. Si combinan esto con la eliminación total de Adobe Flash de la faz de la Tierra tendremos un futuro perfecto.

Por otro lado, en el artículo mencionan que la gente de Firefox y Opera está pensando en introducir la misma funcionalidad, y esos browsers ya tienen buenas defensas contra Flash. ¿Qué opináis vosotros?

Written by valhar2000

November 23rd, 2009 at 11:43 am

12 Comments

Posted in Linux

Grails o la solucion al problema compilado vs interpretado

Supongo que mas de uno de vosotros habra tenido una conversacion en algun instante sobre los pros y los contras de los lenguajes compilados vs interpretados.

Yo la recuerdo cuando trabajaba en Londres. Como sabreis cuando se trata de desarrollar webs hay dos grupos claros de tecnologia a utilizar, una plataforma basada en un lenguaje compilado (segun mi experiencia lo mas utilizado a nivel empresa grande) como J2EE (Java) o .Net (C sharp o Visual Basic) o en un lenguaje interpretado o de script (PHP o Rails).

Ambas tienen sus adeptos y a menudo podrian solucionar el mismo problema. Cual es la peculiaridad mas caracteristica de ambas? Hagamos una breve lista de Pros / Cons (me encantan, las hago hasta con las pivas que conozco).

Pros para la compilacion: Muchos errores o bugs detectados por el compilador, con lo que se salva tiempo (y dinero) en el proceso de desarrollo + QA + mantenimiento de la aplicacion, mas se reduce el margen de error de problemas en produccion en tiempo de ejecucion.

Pros para interpretados: Si quieres cambiar como funciona el codigo no hace falta recompilar todo.

Y de ahi derivamos otra sencilla lista de contras que viene a ser lo mismo a la inversa.

Contras para compilacion: Si encuentras un fallo en tu pequenyo metodo que calcula las milesimas de los precios, tienes que a)organizar un deployment para una fecha acordando con el cliente b) organizar a QA para que testee el release la noche anterior c) crear un release (lo siento, como veis mi vocabulario castellano para cubrir la computacion se quedo en algun lugar del Canal de La Mancha mientras volaba a Londres) completo y madrugar para poner en vivo toda la aplicacion incluyendo un parche para tu pequenyo metodo a las 7 de la manyana, ya que durante el deployment la aplicacion es inacesible y se eliminan todas las sesiones de los usuarios que esten navegando en ese momento.

Contras para los interpretados: Como no tengas un equipo de QA cojonudisimo que haya probado de cabo a rabo la aplicacion y vea que no peta, no dormiras por las noches pensando que en cualquier momento tu aplicacion puede dejar de funcionar en el punto mas insospechado.

Todo ello basado en mi experiencia profesional :)

Bueno pues….. CHAN CHAN CHHAAAAAANN (bombos y confeti) ha llegado una alternativa!! Desde que me mude para trabajar a San Francisco he estado aprendiendo a utilizar Grails sobre Groovy y la verdad estoy encantado. El lenguaje esta construido sobre Java asi que los que sepais Java lo aprendereis en un periquete, pero toma como base la experiencia de cualquier programador de la industria y lo que hace es tomar de manera digamos pre-configurada muchas de las cosas que en cualquier otra plataforma tienes que hacer el 90% de las veces. Por ejemplo, en lugar de tener listas de controladores que apuntan a vistas en un engorroso XML como Struts o Spring, cuando creas un controlador por incluir en el nombre de la clase ‘Controller’ ya lo tomara como un controlador, y le asignara una vista con el mismo nombre con extension .gsp.

El sumum de la ultra usabilidad de Groovy lo he visto a la hora de trabajar con XML y lo explican muy bien aqui:

http://www.ibm.com/developerworks/java/library/j-pg05199/

Me quedo con esta comparativa sobre como parsear (leer) un XML en Java vs Groovy:
Listing 2. Parsing an XML file in Java

import org.xml.sax.SAXException;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.IOException;

public class ParseXml {
  public static void main(String[] args) {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.parse("src/languages.xml");

      //print the "type" attribute
      Element langs = doc.getDocumentElement();
      System.out.println("type = " + langs.getAttribute("type"));

      //print the "language" elements
      NodeList list = langs.getElementsByTagName("language");
      for(int i = 0 ; i < list.getLength();i++) {
        Element language = (Element) list.item(i);
        System.out.println(language.getTextContent());
      }
    }catch(ParserConfigurationException pce) {
      pce.printStackTrace();
    }catch(SAXException se) {
      se.printStackTrace();
    }catch(IOException ioe) {
      ioe.printStackTrace();
    }
  }
}

 

Compare the Java code in Listing 2 with the corresponding Groovy code in Listing 3:
Listing 3. Parsing an XML in Groovy

def langs = new XmlParser().parse("languages.xml")
println "type = ${langs.attribute("type")}"
langs.language.each{
  println it.text()
}

//output:
type = current
Java
Groovy
JavaScript

Es decir, 5 lineas por 26 de Java. Para sacarse la chorra y ponerse a meneeeeee…ejem.

Pero volviendo a nuestro tema… Groovy sigue siendo interpretado, peeeeeero es 100% compatible con Java y la JVM, lo que significa que puedes incluir porciones de Java en tu codigo o en la aplicacion, lo cual significa que puedes mezclar lo mejor de ambos mundos. Ademas incorpora Spring e Hibernate con lo cual siendo una tecnologia nueva se situa a un punto de madurez equivalente a otras tecnologias con anyos en el sector. Ello unido a un uso exhaustivo de Unit Testing para probar tu codigo en tiempo de ejecucion aporta un grado de solucion grande a ambos contras expuestos: Podras cambiar partes de tu codigo en tiempo de ejecucion y tendras las partes mas importantes de tu aplicacion hechas en lenguaje compilado.

Written by miguelangel.fa

November 19th, 2009 at 7:51 am

15 Comments

Posted in Uncategorized