|Portada|Blog|Space|
[Índice] > Bug en wc
Como todos sabrán, el wc tiene un serio bug, y es que al mostrar el más
de 2^63-1 líneas da overflow y arranca a contar desde -2^63. Por eso
mismo y porque estaba aburrido fue que decidí hacerme en sed un «wc -l»
¡que no tiene un máximo de líneas!
Obvio que en realidad no es un bug del wc.
cat archivo | sed -ne 'g;s/^9*$/0&/;s/9*$/-0123456789-&/
s/\(.\)-.*\1\(.\).*-/\2-/;h;s/.*-//;s/./0/g;G;s/\(.*\)\n\(.*\)-.*/\2\1/;h;$s/./&/p'
Como habrán visto quedó absurdamente largo, y eso es porque decidí desde
un principio hacerlo usando única y exclusivamente las instrucciones s,
g, G y h.
Voy a pasar a explicarlo de a poco:
cat archivo: Muestra el archivo
sed -ne: Hace que no muestre cada línea que procesa, y tira solamente
información cuando le pedimos con p. Por cada línea que procesa lo
que hace es ejecutar el script que mostramos a continuación.
g: Obtiene desde la "RAM" (llamado de ahora en más "pattern space") el
valor del string guardado desde el paso anterior. En la primer
iteración obtiene un string vacío.
s/^9*$/0&/: Acá metemos un cero a la izquierda si todo el texto
presente (un número en nuestro caso) está formado solamente por
nueves.
s/9*$/-0123456789-&/: Justito antes de todos los nueves metemos el
texto: -0123456789-. Nótese la diferencia con el caso anterior, en
que no estamos exigiendo que el número esté formado exclusivamente
por nueves, se debe a que no pusimos el ^.
s/\(.\)-.*\1\(.\).*-/\2-/: Acá es donde se realiza la suma :)
capturando en número siguiente al que quedó antes del primer guión.
De esta forma logramos sumarle 1, y ya que estamos borramos los
números del medio dejando solamente un guión.
Por ejemplo si la entrada era 12-0123456789-999, sale de acá
quedando así: 13-999
h: Guardamos esa especie de número en el "pattern space"
s/.*-//: Borramos todo lo anterior al guión que dejamos recién, esto
hace que queden solamente los nueves.
s/./0/g: Cambiamos todas las letras presentes por ceros, recordar que
solo habían quedado nueves.
G: Obtenemos el "pattern space" que habíamos guardado recién,
dejándolo a continuación de los ceros y poniendo un \n en el medio.
En nuestro antiguo ejemplo tendríamos 000\n13-999
s/\(.*\)\n\(.*\)-.*/\2\1/: Ordenamos entonces las cosas quedándonos
con el número que había en el pattern space borrando lo que había
después del guión y el guión inclusive, borrando además el \n y
agregando a continuación los ceros que nos habían restado poner.
h: Guardamos el resultado en el pattern space pronto para procesar la
siguiente línea.
$s/./&/p: Y si estamos en la última línea mostramos el resultado,
podría haber usado la instrucción «p» pero eso hubiera sido una
violiación a las normas, por eso uso solamente el modificador p.
Les dejo como ejercicio buscar alternativas!
---------
Los documentos en este sitio se encuentran licenciados bajo la GFDL.
Ver comentarios: [Hay i comentarios]
Para agregar un comentario: agregue a la URL: ?do=show_comment_form (explicación)