Edición de archivos con Perl#

Descripción#

Perl es un lenguaje de programación interpretado que se especializa en el procesamiento de texto y programación web. Se destaca por ser breve, efectivo y dinámico, lo que permite que la codificación sea más sencilla para los programadores.

En el área de analítica, su función se enfoca en la extracción, limpieza y procesamiento de archivos de texto teniendo como ventaja la fácil conexión a bases de datos relacionales.

Manual y ayuda en línea#

man perl
[1]:
%%bash
# curl -L http://xrl.us/installperlnix | bash

Impresión de líneas específicas#

[2]:
%%bash
#
# se imprimen los primeros 30 números a un archivo
#
seq 30 > out.1
[3]:
%%bash
#
# imprime la línea 3
#
perl -ne 'print if $.==3' out.1
3
[4]:
%%bash
#
# imprime las líneas 3 a 6
#
perl -ne 'print if 3..6' out.1
3
4
5
6
[5]:
%%bash
#
# imprime las líneas 3 a 6 y 11 a 13
#
perl -ne 'print if 3..6; print if 11..13' out.1
3
4
5
6
11
12
13

Filtrado#

[6]:
%%bash
#
# Imprime las lineas que contengan un 1
#
perl -ne 'print if /1/i' out.1
1
10
11
12
13
14
15
16
17
18
19
21

La opción -n indica que no debe imprimirse en pantalla cada línea leída del archivo out.1. La cadena /1/ indica la expresión regular (en este caso que la línea contenga un 1 y los / son delimitadores). La p al final indica que se imprima la línea. Nóte que esta funcionalidad es similar a la dada por grep.

[7]:
%%bash
#
# Imprime las líneas que tengaun un 1 al final
#
perl -ne 'print if /[1]$/' out.1
1
11
21
[8]:
%%bash
#
# Imprime las líneas que tengan un 1 al inicio
#
perl -ne 'print if /^[1]/' out.1
1
10
11
12
13
14
15
16
17
18
19
[9]:
%%sh
#
# Líneas que tienen un 1 al inicio y no tienen un 1 al final
#
perl -ne 'print if /^[1]/ && !/[1]$/' out.1
10
12
13
14
15
16
17
18
19

Sea el siguiente archivo:

[10]:
%%bash
cat > out.1 <<EOF
1  ABC 11
2  BBB 12
3  CCC 13
4x DDD 2
5y EEE 3
1x FAF 4
2y GAF 4
3  HAA 5
EOF

Para imprimir en pantalla todas las líneas que contienen A se usa el comando:

[11]:
%%bash
#
# imprime todas las lineas que tengan una A
#
perl -ne 'print if /A/i' out.1
1  ABC 11
1x FAF 4
2y GAF 4
3  HAA 5
[12]:
%%sh
perl -ne 'print if m#A#' out.1
1  ABC 11
1x FAF 4
2y GAF 4
3  HAA 5

Observe que la sintaxis anterior permite buscar de forma literal elementos dentro del texto mientras que en la primera la letraA se interpreta como mayúscula o minúscula.

El siguiente comando imprime todas las líneas que contienen 1 al inicio de la frase:

Para obtener la concatenación de dos condiciones se utiliza el simbolo && y para obtener el complemento de la busqueda el simbolo !.

[13]:
%%bash
#
# imprime todas las lineas que tengan una A y que
# no tengan un 4
#
perl -ne 'print if /A/ && !/4/' out.1
1  ABC 11
3  HAA 5

Es posible obtener un filtro de los elementos que contienen mas de una expresión a través de la función index.

[14]:
%%bash
s='3  C' perl -ne 'print if index($_, $ENV{s})==0' out.1
3  CCC 13

En el caso anterior, se buscó la expresión 3  C al principio de la frase (==0).

[15]:
%%bash
#
# Es posible indexar sobre los elementos de una expresión
# reconociendo los espacios como separadores por defecto.
#
perl -lane 'print $F[0]' out.1
1
2
3
4x
5y
1x
2y
3

Para realizar comparaciones entre texto se utiliza eq como == y ne como !=, e igualmente para la impresión del resultado es posible establecer el separador deseado.

[16]:
%%bash
perl -lane 'print $F[1] if $F[0] eq "3"' out.1
CCC
HAA
[17]:
%%bash
perl -lane '$,="-"; print $F[2],$F[3] if $F[0] ne "3"' out.1
11-
12-
2-
3-
4-
4-
[18]:
%%bash
perl -ne 'BEGIN{$\="----\n"} print' out.1
1  ABC 11
----
2  BBB 12
----
3  CCC 13
----
4x DDD 2
----
5y EEE 3
----
1x FAF 4
----
2y GAF 4
----
3  HAA 5
----

Expresiones regulares#

Existen expresiones que facilitan la busquedas de patrones especificos. Algunas de ellas son:

  • * - Conincide 0 o mas veces

  • + - Conincide 1 o mas veces

  • ? - Conincide 0 o 1 vez

  • \d - Elementos numéricos (o \D para el complemento de la búsqueda)

  • \w - Cualquier caracter de una palabra (o \W ara el complemento de la busqueda)

  • $& - Parar referirse a todos los elementos que detectados

  • {n,} - Conincide por lo menos n veces.

Sea el siguiente archivo:

[19]:
%%bash
cat > out.2 <<EOF
1980-JAN-1+1:0:1.134
1980-JAN-5+1:0:1.12
1982-JAN-13+10:12:42.33
EOF

Se desea formatear la fecha y la hora, es decir, la primera línea:

1980-JAN-1+1:0:1.134

debe cambiarse por:

1980-JAN-01 01:00:01

Las expresiones regulares siguen una estructura similar a las de sed, teniendo un patrón a identificar y una expresión con la cual reemplazar o editar el elemtno anterior.

s/patrón/reemplazo

Consulte la guía de usuario de las expresiones regulares en Perl aquí

[20]:
%%bash
perl -pe 's/\+/ /' out.2 > out.3
cat out.3
1980-JAN-1 1:0:1.134
1980-JAN-5 1:0:1.12
1982-JAN-13 10:12:42.33
[21]:
%%bash
perl -pe 's/-(\w+)-(\d)\b/-$1-0$2/g' out.3 > out.4
cat out.4
1980-JAN-01 1:0:1.134
1980-JAN-05 1:0:1.12
1982-JAN-13 10:12:42.33

La explicación del comando anterior es la siguiente. El patrón de entrada está conformado por los siguientes elementos:

  • El caracter -.

  • Una palabra \w+. Las secuencias ( y ) especifican que el dígito reconocido debe recordarse. Pueden existir varias cadenas a recordar; la primera cadena es $1, la segunda cadena es $2 y así sucesivamente. (?1) se utiliza para recordar una expresión regular anterior.

  • Un dígito \d.

  • Un espacio \b.

El patrón de salida indica que:

  • Se imprime el caracter -.

  • Luego JAN.

  • A continuación el caracter - seguido de 0 y del dígito reconocido de $2.

[22]:
%%bash
perl -pe 's/ (\d):(\d):/ 0$1:0$2:/g' out.4 > out.5
cat out.5
1980-JAN-01 01:00:1.134
1980-JAN-05 01:00:1.12
1982-JAN-13 10:12:42.33
[23]:
%%bash
perl -pe 's/:(\d*)\.(\d)+/:$1/g' out.5 > out.6
cat out.6
1980-JAN-01 01:00:1
1980-JAN-05 01:00:1
1982-JAN-13 10:12:42
[24]:
%%bash
perl -pe 's/:(\d)\b/:0$1/g' out.6 > out.7
cat out.7
1980-JAN-01 01:00:01
1980-JAN-05 01:00:01
1982-JAN-13 10:12:42
[25]:
%%bash
rm out.*

Sea el siguiente archivo:

[26]:
%%bash
cat > out.3 <<EOF
A B C 1
E F G 2
A D F 3
B C H 4
E C A 5
E A A 6
EOF

Es posible utilizar algunos comandos especiales para editar los registros en cuanto a su composición.

[27]:
%%bash
#
# Detecta la información entre un elemento y otro
#
perl -pe 's/E.*2//' out.3
A B C 1

A D F 3
B C H 4
E C A 5
E A A 6
[28]:
%%bash
#
# Permite filtrar elementos de una expresión de acuerdo a su tipo
#
perl -pe 's/\w{1}//' out.3
 B C 1
 F G 2
 D F 3
 C H 4
 C A 5
 A A 6
[29]:
%%bash
perl -lane 'print "@F[-1]"' out.3
1
2
3
4
5
6
[30]:
%%bash
#
# Es posible contar los elementos de una frase a través de $.
#
perl -lne 'print reverse split//' out.3
1 C B A
2 G F E
3 F D A
 4 H C B
5 A C E
6 A A E

Resumen#

## imprime la línea 3
perl -ne 'print if $.==3' out.1

## imprime las líneas 3 a 6
perl -ne 'print if 3..6' out.1

## imprime las líneas 3 a 6 y 11 a 13
perl -ne 'print if 3..6; print if 11..13' out.1

## Imprime las lineas que contengan un 1
perl -ne 'print if /1/i' out.1

## Imprime las líneas que tengaun un 1 al final
perl -ne 'print if /[1]$/' out.1

## Imprime las líneas que tengan un 1 al inicio
perl -ne 'print if /^[1]/' out.1

## Líneas que tienen un 1 al inicio y no tienen un 1 al final
perl -ne 'print if /^[1]/ && !/[1]$/' out.1

## imprime todas las lineas que tengan una A
perl -ne 'print if /A/i' out.1

## imprime todas las lineas que tengan una A y que
## no tengan un 4
perl -ne 'print if /A/ && !/4/' out.1
[31]:
!rm out.*