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#
Manual: https://www.perl.org/learn.html
Ayuda:
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 menosn
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 de0
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.*