<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Polar Geek &#187; shell</title>
	<atom:link href="http://www.polargeek.net/tag/shell/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.polargeek.net</link>
	<description>Polar Geek es un blog sobre desarrollo web en general (php, Javascript, jquery, css..), diseño, programación y recursos de todo tipo.</description>
	<lastBuildDate>Wed, 01 Sep 2010 11:58:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Introducción a AWK (II)</title>
		<link>http://www.polargeek.net/introduccion-a-awk-ii/</link>
		<comments>http://www.polargeek.net/introduccion-a-awk-ii/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 15:38:43 +0000</pubDate>
		<dc:creator>José</dc:creator>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[awk]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://www.polargeek.net/?p=1307</guid>
		<description><![CDATA[Por dónde seguir Este es el segundo post de una seria sobre AWK. El primero lo puedes encontrar aquí. Si no le has echado un vistazo te recomiendo hacerlo. Sigamos ahora por donde lo dejamos. Operaciones matemáticas con varias columnas Una de las últimas cosas que hicimos en el post anterior sobre AWK fue sumar [...]]]></description>
			<content:encoded><![CDATA[<h2>Por dónde seguir</h2>
<p>Este es el segundo post de una seria sobre AWK. El primero lo puedes encontrar <a href="http://www.polargeek.net/introduccion-a-awk-i/">aquí</a>. Si no le has echado un vistazo te recomiendo hacerlo. Sigamos ahora por donde lo dejamos.<br />
<img title="Puente de San Francisco" src="http://static.polargeek.net/uploads/puente_awk.jpg"/></p>
<h2>Operaciones matemáticas con varias columnas</h2>
<p>Una de las últimas cosas que hicimos en el post anterior sobre AWK fue sumar una columna para ver el total. Lo cierto es que hay muchas más posibilidades. Teniendo el mismo archivo que antes:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">$ cat inventario.txt 
Ene  13  25  15 115
Feb  15  32  24 226
Mar  15  24  34 228
Abr  31  52  63 420
May  16  34  29 208
Jun  31  42  75 492
Jul  24  34  67 436
Ago  15  34  47 316
Sep  13  55  37 277
Oct  29  54  68 525
Nov  20  87  82 577
Dic  17  35  61 401
&nbsp;
Ene  21  36  64 620
Feb  26  58  80 652
Mar  24  75  70 495
Abr  21  70  74 514</pre></td></tr></table></div>

<p>Vamos ahora a sumar lo obtenido en los meses de Enero. Recordemos que la última columna se refiere a los euros que obtenemos ese mes.<br />
Así que tendríamos que hacer algo como: &#8220;Si estamos en Enero entonces súmalo al total. Cuando terminemos con todos los &#8216;Eneros&#8217; entonces imprimimos el resultado&#8221;. Esto en AWK sería:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'$1==&quot;Ene&quot; { sum=sum+$5 }; END {print &quot;Hemos ganado &quot; sum &quot;€ en total con todos los meses de Enero&quot;}'</span> inventario.txt</pre></td></tr></table></div>

<p>Como vemos ahora la condición es que estemos en el mes de Enero (&#8220;Ene&#8221;), si es así lo sumamos. Al final, con END, indicamos la salida. Podemos reducir la expresión de la suma, con el operador &#8220;+=&#8221;, quedando así:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'$1==&quot;Ene&quot; { sum += $5 }; END {print &quot;Hemos ganado &quot; sum &quot;€ en total con todos los meses de Enero&quot;}'</span> inventario.txt</pre></td></tr></table></div>

<p>Esto, evidentemente produce la misma salida:</p>
<div class="bubble_wrapper">
<div class="pmeta_bubble_bg pmeta_bubble_bg_ok">
<div class="box-inner">
Hemos ganado 735€ en total con todos los meses de Enero
</div>
</div>
</div>
<h2>Variables Especiales o built-in</h2>
<p>Existen una serie de variables &#8220;especiales&#8221; o como las queramos llamar, que suponen una tremenda ayuda a la hora de usar AWK. En realidad ya hemos utilizado una en el anterior post, &#8220;FNR&#8221;, que indicaba el número de línea actual en el que estamos. Pero hay más.</p>
<h3>FS (Field Separator)</h3>
<p>Esta variable permite decir que vamos a usar como separación, por defecto su valor es &#8221; &#8220;, como podemos ver en los archivos que hemos procesado hasta ahora, los campos estaban separados por un espacio. Pero este valor puede cambiar, simplemente haciendo una asignación. Imaginemos que tenemos el siguiente archivo:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">$ cat contactos.txt
Carlos García,Calle Nueva N 27,Barcelona, 08124,carlos@gmail.com
Rocío López,Calle Vieja N 2,Madrid,28562,rocio@google.com
Patricia Díaz,Calle Secreta N 11,Cádiz,72723,patricia@hotmail.com</pre></td></tr></table></div>

<p>En él se puede observar que hay datos de contactos, separados por comas. Y como ya sabemos el espacio es el separador que nos vale. </p>
<p>Imaginemos que vamos a hacer una lista de correo, y queremos extraer los correos de nuestros contactos. Se puede plantear la opción de modificar el archivo y cambiar las comas por espacios, pero lo cierto es que ya hay espacios, y si luego vamos a referirnos a la dirección, en $2, solo obtendríamos &#8220;Calle&#8221;, puesto que hay más espacios dentro de ese campo.</p>
<p>Así que la opción pasa por asignar el valor de &#8220;,&#8221; a la variable FS. Esto es algo que tenemos que hacer antes que nada, y para ello tenemos &#8220;BEGIN&#8221;. La instrucción quedaría así:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'BEGIN { FS = &quot;,&quot; } ; { print $5 }'</span> .<span style="color: #000000; font-weight: bold;">/</span>contactos.txt</pre></td></tr></table></div>

<p>Nótese que aquí $5 se refiere al 5º campo entre comas que tenemos por línea, así, la salida sería:</p>
<div class="bubble_wrapper">
<div class="pmeta_bubble_bg pmeta_bubble_bg_ok">
<div class="box-inner">
carlos@gmail.com<br />
rocio@google.com<br />
patricia@hotmail.com
</div>
</div>
</div>
<p>Aquí hay un detalle, si en una línea tenemos 2 espacios seguidos, sería como tener &#8220;,,&#8221; es decir, una columna vacía, en cambio, si hay 2 espacios AWK no lo interpreta como un campo vacío entre medias, y se lo salta. Esto es por el lenguaje y para poder emular el mismo comportamiento necesitamos expresiones regulares, algo que veremos más adelante con detenimiento. </p>
<h3>NF (Number of Fields)</h3>
<p>Esta variable contiene el número de campos en la línea actual. Aprovechando el archivo anterior, para saber con cuántos campos estamos tratando:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'BEGIN { FS = &quot;,&quot; } ; { print NF }'</span> .<span style="color: #000000; font-weight: bold;">/</span>contactos.txt</pre></td></tr></table></div>

<p>Y su salida será:</p>
<div class="bubble_wrapper">
<div class="pmeta_bubble_bg pmeta_bubble_bg_ok">
<div class="box-inner">
5<br />
5<br />
5
</div>
</div>
</div>
<p>Es decir, tenemos 5 campos por línea, en todas las líneas. Se puede aprovechar el contenido de esta variable para referirse al último campo. Puesto que, de la misma forma que:</p>
<pre>
<code>
5 = 5
$5 es el contenido del campo 5
</code>
</pre>
<p>Con NF, pasa lo mismo:</p>
<pre>
<code>
NF = 5
$NF = contenido del campo 5.
</code>
</pre>
<p>Así que aprovechando esto, tendremos:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'BEGIN { FS = &quot;,&quot; } ; { print $NF }'</span> .<span style="color: #000000; font-weight: bold;">/</span>contactos.txt</pre></td></tr></table></div>

<p>Y la salida sería exactamente la misma que si hubiéramos puesto $5.</p>
<div class="bubble_wrapper">
<div class="pmeta_bubble_bg pmeta_bubble_bg_ok">
<div class="box-inner">
carlos@gmail.com<br />
rocio@google.com<br />
patricia@hotmail.com
</div>
</div>
</div>
<p>Así que usando NF, no nos tenemos que preocupar de contar los campos, mientras que tengamos claro que lo que queremos obtener está en el último campo de cada línea.</p>
<h3>NR (Number of Record)</h3>
<p>NR contiene el número de registro en el que estamos, entendiendo registro como línea (aunque podría ser otra cosa, pero lo veremos más adelante). </p>
<p>Es importante que sepamos bien como es el archivo con el que vamos a trabajar, aquí estamos planteando ejemplos de archivos de pocas líneas pero con un archivo de 1000 o 2000 líneas, como puede pasar perfectamente en la realidad, no podemos ver a mano si todos los campos están bien y todo es uniforme. </p>
<p>Así si por ejemplo queremos ver que todas las líneas(registros) de un archivo tienen el mismo número de campos. Lo primero que debemos saber es como va a ser el informe que vamos a procesar, si le hemos pedido a los administrativos que hagan 3 columnas por línea, lo último que van a hacer va a ser eso, así que veamos como mirar si está mal.</p>
<p>El planteamiento es: si esperamos 3 y uno tiene algo distinto, lo decimos. </p>
<p>El archivo es este</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">$ cat informe.txt
Campo1 Campo2 Campo3
Campo1 Campo2 Campo3 Campo4
Campo1 Campo2 Campo3
Campo1 Campo2 Campo3</pre></td></tr></table></div>

<p>Como se puede ver, esperábamos tres campos y en la línea 2, hay 4. Nuestra instrucción quedaría:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'BEGIN { n = 3 }; { 
	if (n != NF) 
		{print &quot;Error en la linea &quot; NR &quot;, tiene &quot; NF &quot; campos.&quot;} 
}'</span> .<span style="color: #000000; font-weight: bold;">/</span>informe.txt</pre></td></tr></table></div>

<p>Y su salida: </p>
<div class="bubble_wrapper">
<div class="pmeta_bubble_bg pmeta_bubble_bg_error">
<div class="box-inner">
Error en la linea 2, tiene 4 campos.
</div>
</div>
</div>
<p>Si nos fijamos, ahora no nos interesa el contenido del registro número NF($NF), sino el valor en sí, es decir, el número de campos por línea, por ello usamos NF simplemente, que contendrá 3, 4, 3 y 3, según avance la ejecución. Además, NR nos aporta más información sobre el error, dicíendonos en que línea hay más campos de los esperados. </p>
<p>Dos cosas más a destacar es el uso del if y que existen varias líneas, en el programa. Respecto al uso del if, es como un if en el resto de lenguajes imperativos, con la estructura:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">if (condicion)
   {accion}
else
   {accion2}</pre></td></tr></table></div>

<p>Y que el programa tenga varias líneas no es problema para el shell. Se interpreta como si estuviéramos introduciendo todo en una línea. Recordemos que las comillas simples al principio y al final del programa awk, no pertenecen propiamente al lenguaje, es una forma que tenemos para decirle al shell &#8220;lo que está entre las comillas simples no lo interpretes para ti, solo pásaselo a AWK&#8221;.</p>
<h2>Conclusión</h2>
<p>Hasta aquí llega esta parte, en la próxima veremos que una línea no tiene que ser un registro necesariamente, y profundizaremos más en AWK, con el uso de otras variables especiales y más funcionalidades que podamos darle a este lenguaje.</p>
<p>Fotografía de Maschinenraum (<a href="http://www.flickr.com/photos/petergorges/3117702817/">Flickr</a>)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.polargeek.net/introduccion-a-awk-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducción a AWK (I)</title>
		<link>http://www.polargeek.net/introduccion-a-awk-i/</link>
		<comments>http://www.polargeek.net/introduccion-a-awk-i/#comments</comments>
		<pubDate>Wed, 20 Jan 2010 23:17:21 +0000</pubDate>
		<dc:creator>José</dc:creator>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[awk]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://www.polargeek.net/?p=889</guid>
		<description><![CDATA[El lenguaje AWK es un lenguaje que permite muchas cosas, su utilidad más común es buscar líneas en archivos de texto y ejecutar acciones especificadas para esa línea. Normalmente un programa AWK es del estilo a patrón { accion } patrón { accion } patrón { accion } ... Se ejecuta de las dos siguientes [...]]]></description>
			<content:encoded><![CDATA[<h2>El lenguaje</h2>
<p>AWK es un lenguaje que permite muchas cosas, su utilidad más común es buscar líneas en archivos de texto y ejecutar acciones especificadas para esa línea. Normalmente un <strong>programa AWK</strong> es del estilo a</p>
<pre><code>
patrón { accion }
patrón { accion }
patrón { accion }
...
</code>
</pre>
<p>Se ejecuta de las dos siguientes formas, dependiendo de si tenemos el programa en un archivo o no. <em>programa</em> tiene la pinta que hemos visto antes.</p>
<pre><code>
# Esto es un comentario. Las comillas simples suelen ser requeridas
# para poder poner varias lineas y que el shell tome programa como
# un solo argumento
awk ’programa’ entrada_1 entrada_2 ...
</code>
</pre>
<p>Y con el programa en un archivo</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Aqui el archivo_programa contiene el programa awk</span>
<span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #660033;">-f</span> archivo_programa entrada_1 entrada_2 ...</pre></td></tr></table></div>

<p>Nota: Si no se especifica un archivo de entrada, se utiliza la entrada estándar.</p>
<h2>Instalación</h2>
<p>AWK, o implementaciones parecidas como gawk (de GNU AWK), vienen instalados por defecto en la mayoría de los sistemas operativos. (MAC, Linux, Unix) y para Windows sigue <a href="http://gnuwin32.sourceforge.net/packages/gawk.htm">este enlace</a> para instalar gawk, si no lo tienes instalado ya.</p>
<h2>Primeros Pasos</h2>
<p>Teniendo en un archivo, llamésmole agenda.txt lo siguiente</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">$ cat agenda.txt
Maria        938563212    maria@gmail.com   B
Irene        944683129    irene@hotmail.com A
Pedro        659817325    pedro@google.com  A
Carlos       982256987    carlos@gmail.com  A
Francisco    669332112    paco@hotmail.com  C
Julia        678963888    julia@gmail.com   B
Pedro        928975641    pedro@msn.com     B
Manuel       698788221    manuel@trep.es    A
César        956213584    cesar@hotmail.com A
Javier       918745251    javi@google.com   C
Antonio      666999879    antonio@msn.com   C</pre></td></tr></table></div>

<p>Ahora por ejemplo, obtengamos todas las líneas de las personas que se llaman Pedro.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"> <span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'/Pedro/ { print $0 }'</span> agenda.txt</pre></td></tr></table></div>

<p>Cada parte tiene su significado, como se puede ver en la imagen:</p>
<div class="img"><img src="http://static.polargeek.net/uploads/awk1.jpg" alt="" /></div>
<p>La salida de esto es:</p>
<div class="bubble_wrapper">
<div class="pmeta_bubble_bg pmeta_bubble_bg_ok">
<div class="box-inner">Pedro        659897325    pedro@google.com  A<br />
Pedro        928975641    pedro@msn.com     B</div>
</div>
</div>
<p>Es decir, en $0, $1&#8230;$N, siendo N el nº de columnas, tendremos ciertos valores, siempre referidos a la línea <strong>actual</strong> que está procesando AWK. Recuerda siempre que en $0 tenemos la línea que estamos procesando completa. Por ejemplo, con nuestra agenda tendremos:</p>
<p><img src="http://static.polargeek.net/uploads/columnas.jpg" border="0" alt="" /></p>
<p>Es decir que podemos referirnos a una columna en concreto, para buscar el teléfono de alguien, por ejemplo.<br />
Pongamos que queremos llamar a Julia, en ese caso hacemos:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'$1==&quot;Julia&quot; { print &quot;El nº de &quot; $1 &quot; es &quot; $2 }'</span> agenda.txt</pre></td></tr></table></div>

<p>Explicación: En $1 se tendrá el contenido de la primera columna de la línea que estamos procesando, por lo que cuando lleguemos a que en la 1ª columna hay &#8220;Julia&#8221; imprimimos &#8220;El nº de (contenido de la 1ª columna) es (contenido de la segunda columna)&#8221;. Está claro, que la parte &#8220;patrón&#8221; a la que nos referiamos al principio no tiene por qué ser una expresión regular, puede ser una condición, como en este ejemplo.</p>
<p>Así que la salida de esto, efectivamente, es:</p>
<div class="bubble_wrapper">
<div class="pmeta_bubble_bg pmeta_bubble_bg_ok">
<div class="box-inner">El nº de Julia es 678963888</div>
</div>
</div>
<p>Y en otro archivo, para más ejemplos, tenemos un inventario, siendo la última columna la cantidad que hemos facturado en ese mes.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">$ cat inventario.txt 
Ene  13  25  15 115
Feb  15  32  24 226
Mar  15  24  34 228
Abr  31  52  63 420
May  16  34  29 208
Jun  31  42  75 492
Jul  24  34  67 436
Ago  15  34  47 316
Sep  13  55  37 277
Oct  29  54  68 525
Nov  20  87  82 577
Dic  17  35  61 401
&nbsp;
Ene  21  36  64 620
Feb  26  58  80 652
Mar  24  75  70 495
Abr  21  70  74 514</pre></td></tr></table></div>

<p>Veamos cual es la suma total que nos hemos llevado en el primer año.</p>
<pre class="brush: shell;wrap-lines: false">
 awk 'FNR&lt;=12 { sum=sum+$5 }; END {print "Hemos ganado " sum "€ este año"}' inventario.txt
</pre>
<p>Explicación: AWK tiene una serie de valores reservados que podemos utilizar. En este caso, usamos FNR, que tiene el número de línea en el que estamos. Así que como un año tiene 12 meses, la condición para que se ejecute nuestro programa es que FNR, es decir, el nº de línea, sea menor o igual a 12. Si es así vamos acumulando en la variable &#8220;sum&#8221; la suma total del dinero de la columna 5ª de cada línea, y cuando terminamos (END) imprimimos el resultado.</p>
<p>La salida de este es:</p>
<div class="bubble_wrapper">
<div class="pmeta_bubble_bg pmeta_bubble_bg_ok">
<div class="box-inner">Hemos ganado 4221€ este año</div>
</div>
</div>
<p>Bueno AWK tiene muchas posibilidades, y bien utilizado puede sacarnos de apuros sin necesidad de utilizad ni XML, ni MySQL, ni Excel, simplemente con un archivo de texto plano, y dándole un significado a cada columna. Algunas utilidades reales que se me ocurren: una agenda, una lista de la compra con sus precios, una plantilla, tareas pendientes&#8230;en fin el límite lo pones tú.</p>
<p><del datetime="2010-03-03T14:46:34+00:00">Dentro de poco haré más post sobre AWK</del>, esto era solo una introducción.<br />
Edito: Ya está online <a href="http://www.polargeek.net/introduccion-a-awk-ii/">la 2ª parte de esta serie de posts sobre AWK</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.polargeek.net/introduccion-a-awk-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
