Unix / Linux - Expresiones regulares con SED
En este capítulo, discutiremos en detalle sobre las expresiones regulares con SED en Unix.
Una expresión regular es una cadena que se puede utilizar para describir varias secuencias de caracteres. Las expresiones regulares son utilizadas por varios comandos Unix diferentes, incluyendoed, sed, awk, grep, y en una medida más limitada, vi.
aquí SED representa stream editor. Este editor orientado a la transmisión fue creado exclusivamente para ejecutar scripts. Por lo tanto, toda la entrada que ingresa pasa y va a STDOUT y no cambia el archivo de entrada.
Invocando sed
Antes de comenzar, asegurémonos de tener una copia local de /etc/passwd archivo de texto para trabajar sed.
Como se mencionó anteriormente, sed se puede invocar enviándole datos a través de una tubería de la siguiente manera:
$ cat /etc/passwd | sed
Usage: sed [OPTION]... {script-other-script} [input-file]...
-n, --quiet, --silent
suppress automatic printing of pattern space
-e script, --expression = script
...............................
los cat comando vuelca el contenido de /etc/passwd a seda través de la tubería en el espacio del patrón de sed. El espacio de patrón es el búfer de trabajo interno que sed usa para sus operaciones.
La sintaxis general de sed
A continuación se muestra la sintaxis general de sed:
/pattern/action
Aquí, pattern es una expresión regular y actiones uno de los comandos dados en la siguiente tabla. Sipattern se omite, action se realiza para cada línea como hemos visto anteriormente.
El carácter de barra (/) que rodea el patrón es obligatorio porque se utilizan como delimitadores.
No Señor. | Rango y descripción |
---|---|
1 | p Imprime la linea |
2 | d Borra la linea |
3 | s/pattern1/pattern2/ Sustituye la primera aparición de patrón1 con patrón2 |
Eliminar todas las líneas con sed
Ahora entenderemos cómo eliminar todas las líneas con sed. Invoque sed de nuevo; pero ahora se supone que el sed usa elediting command delete line, denotado por una sola letra d -
$ cat /etc/passwd | sed 'd'
$
En lugar de invocar sed enviándole un archivo a través de una tubería, se puede indicar al sed que lea los datos de un archivo, como en el siguiente ejemplo.
El siguiente comando hace exactamente lo mismo que en el ejemplo anterior, sin el comando cat:
$ sed -e 'd' /etc/passwd
$
Las direcciones sed
El sed también admite direcciones. Las direcciones son ubicaciones particulares en un archivo o un rango donde se debe aplicar un comando de edición en particular. Cuando sed no encuentra direcciones, realiza sus operaciones en cada línea del archivo.
El siguiente comando agrega una dirección básica al comando sed que ha estado usando:
$ cat /etc/passwd | sed '1d' |more
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
$
Observe que el número 1 se agrega antes del delete editmando. Esto le indica al sed que realice el comando de edición en la primera línea del archivo. En este ejemplo, sed eliminará la primera línea de/etc/password e imprima el resto del archivo.
Los rangos de direcciones sed
Ahora entenderemos cómo trabajar con the sed address ranges. Entonces, ¿qué sucede si desea eliminar más de una línea de un archivo? Puede especificar un rango de direcciones con sed de la siguiente manera:
$ cat /etc/passwd | sed '1, 5d' |more
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
$
El comando anterior se aplicará en todas las líneas desde 1 hasta 5. Esto elimina las primeras cinco líneas.
Pruebe los siguientes rangos de direcciones:
No Señor. | Rango y descripción |
---|---|
1 | '4,10d' Las líneas que comienzan a partir de la 4 º hasta el 10 º se eliminan |
2 | '10,4d' Solo se elimina la décima línea, porque el sed no funciona en dirección inversa |
3 | '4,+5d' Esto coincide con la línea 4 del archivo, elimina esa línea, continúa eliminando las siguientes cinco líneas y luego deja de eliminarse e imprime el resto. |
4 | '2,5!d' Esto elimina todo excepto desde la 2ª hasta la 5ª línea |
5 | '1~3d' Esto borra la primera línea, pasa a las siguientes tres líneas y luego borra la cuarta línea. Sed continúa aplicando este patrón hasta el final del archivo. |
6 | '2~2d' Esto le dice a sed que elimine la segunda línea, pase a la siguiente línea, elimine la siguiente línea y repita hasta llegar al final del archivo. |
7 | '4,10p' Las líneas que comienzan a partir de 4 º hasta 10 º se imprimen |
8 | '4,d' Esto genera el error de sintaxis |
9 | ',10d' Esto también generaría un error de sintaxis |
Note - Mientras usa el p acción, debe utilizar la -nopción para evitar la repetición de la impresión de líneas. Compruebe la diferencia entre los siguientes dos comandos:
$ cat /etc/passwd | sed -n '1,3p'
Check the above command without -n as follows −
$ cat /etc/passwd | sed '1,3p'
El comando de sustitución
El comando de sustitución, denotado por s, sustituirá cualquier cadena que especifique con cualquier otra cadena que especifique.
Para sustituir una cadena por otra, sed necesita tener la información sobre dónde termina la primera cadena y comienza la cadena de sustitución. Para ello, procedemos a sujetar las dos cadenas con la barra inclinada (/) personaje.
El siguiente comando sustituye la primera aparición en una línea de la cadena root con la cuerda amrood.
$ cat /etc/passwd | sed 's/root/amrood/'
amrood:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
..........................
Es muy importante tener en cuenta que sed sustituye solo la primera aparición en una línea. Si la raíz de la cadena aparece más de una vez en una línea, solo se reemplazará la primera coincidencia.
Para que sed realice una sustitución global, agregue la letra g hasta el final del comando de la siguiente manera:
$ cat /etc/passwd | sed 's/root/amrood/g'
amrood:x:0:0:amrood user:/amrood:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
...........................
Banderas de sustitución
Hay una serie de otros indicadores útiles que se pueden pasar además del g flag, y puede especificar más de uno a la vez.
No Señor. | Bandera y descripción |
---|---|
1 | g Reemplaza todos los partidos, no solo el primer partido |
2 | NUMBER Reemplaza solo NUMBER th partido |
3 | p Si se realizó una sustitución, imprime el espacio del patrón |
4 | w FILENAME Si se realizó una sustitución, escribe el resultado en FILENAME |
5 | I or i Coincidencias sin distinción entre mayúsculas y minúsculas |
6 | M or m Además del comportamiento normal de los caracteres especiales de expresión regular ^ y $, este indicador hace que ^ coincida con la cadena vacía después de una nueva línea y $ para que coincida con la cadena vacía antes de una nueva línea |
Usar un separador de cadenas alternativo
Suponga que tiene que hacer una sustitución en una cadena que incluye el carácter de barra diagonal. En este caso, puede especificar un separador diferente proporcionando el carácter designado después dels.
$ cat /etc/passwd | sed 's:/root:/amrood:g'
amrood:x:0:0:amrood user:/amrood:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
En el ejemplo anterior, hemos utilizado : como el delimiter en lugar de barra oblicua / porque estábamos intentando buscar /root en lugar de la raíz simple.
Reemplazo con espacio vacío
Utilice una cadena de sustitución vacía para eliminar la cadena raíz de la /etc/passwd archivo completo -
$ cat /etc/passwd | sed 's/root//g'
:x:0:0::/:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
Sustitución de dirección
Si quieres sustituir la cadena sh con la cuerda quiet solo en la línea 10, puede especificarlo de la siguiente manera:
$ cat /etc/passwd | sed '10s/sh/quiet/g'
root:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/quiet
De manera similar, para hacer una sustitución de rango de direcciones, puede hacer algo como lo siguiente:
$ cat /etc/passwd | sed '1,5s/sh/quiet/g'
root:x:0:0:root user:/root:/bin/quiet
daemon:x:1:1:daemon:/usr/sbin:/bin/quiet
bin:x:2:2:bin:/bin:/bin/quiet
sys:x:3:3:sys:/dev:/bin/quiet
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
Como puede ver en la salida, las primeras cinco líneas tenían la cadena sh cambiado a quiet, pero el resto de las líneas quedaron intactas.
El comando de emparejamiento
Usarías el p opción junto con la -n opción para imprimir todas las líneas coincidentes de la siguiente manera:
$ cat testing | sed -n '/root/p'
root:x:0:0:root user:/root:/bin/sh
[[email protected] amrood]# vi testing
root:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
Usar expresión regular
Al hacer coincidir patrones, puede utilizar la expresión regular que proporciona más flexibilidad.
Verifique el siguiente ejemplo que coincide con todas las líneas que comienzan con daemon y luego las elimina:
$ cat testing | sed '/^daemon/d'
root:x:0:0:root user:/root:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
A continuación se muestra el ejemplo que elimina todas las líneas que terminan con sh -
$ cat testing | sed '/sh$/d'
sync:x:4:65534:sync:/bin:/bin/sync
La siguiente tabla enumera cuatro caracteres especiales que son muy útiles en expresiones regulares.
No Señor. | Descripción del personaje |
---|---|
1 | ^ Coincide con el comienzo de las líneas |
2 | $ Coincide con el final de las líneas |
3 | . Coincide con cualquier carácter individual |
4 | * Coincide con cero o más ocurrencias del carácter anterior |
5 | [chars] Coincide con cualquiera de los caracteres dados en chars, donde chars es una secuencia de caracteres. Puede utilizar el carácter - para indicar un rango de caracteres. |
Personajes a juego
Mira algunas expresiones más para demostrar el uso de metacharacters. Por ejemplo, el siguiente patrón:
No Señor. | Expresión y descripción |
---|---|
1 | /a.c/ Coincide con líneas que contienen cadenas como a+c, a-c, abc, matchy a3c |
2 | /a*c/ Coincide con las mismas cadenas junto con cadenas como ace, yaccy arctic |
3 | /[tT]he/ Coincide con la cuerda The y the |
4 | /^$/ Coincide con líneas en blanco |
5 | /^.*$/ Coincide con una línea completa, sea lo que sea |
6 | / */ Coincide con uno o más espacios |
7 | /^$/ Partidos blank líneas |
La siguiente tabla muestra algunos conjuntos de caracteres de uso frecuente:
No Señor. | Conjunto y descripción |
---|---|
1 | [a-z] Coincide con una sola letra minúscula |
2 | [A-Z] Coincide con una sola letra mayúscula |
3 | [a-zA-Z] Coincide con una sola letra |
4 | [0-9] Coincide con un solo número |
5 | [a-zA-Z0-9] Coincide con una sola letra o número |
Palabras clave de clase de personaje
Algunas palabras clave especiales están comúnmente disponibles para regexps, especialmente las utilidades GNU que emplean regexps. Son muy útiles para las expresiones regulares sed ya que simplifican las cosas y mejoran la legibilidad.
Por ejemplo, los personajes a through z y los personajes A through Z, constituyen una de esas clases de caracteres que tiene la palabra clave [[:alpha:]]
Usando la palabra clave de la clase de caracteres alfabéticos, este comando imprime solo aquellas líneas en el /etc/syslog.conf archivo que comienza con una letra del alfabeto -
$ cat /etc/syslog.conf | sed -n '/^[[:alpha:]]/p'
authpriv.* /var/log/secure
mail.* -/var/log/maillog
cron.* /var/log/cron
uucp,news.crit /var/log/spooler
local7.* /var/log/boot.log
La siguiente tabla es una lista completa de las palabras clave de clase de caracteres disponibles en GNU sed.
No Señor. | Clase de personaje y descripción |
---|---|
1 | [[:alnum:]] Alfanumérico [az AZ 0-9] |
2 | [[:alpha:]] Alfabético [az AZ] |
3 | [[:blank:]] Caracteres en blanco (espacios o tabulaciones) |
4 | [[:cntrl:]] Personajes de control |
5 | [[:digit:]] Números [0-9] |
6 | [[:graph:]] Cualquier carácter visible (excluye los espacios en blanco) |
7 | [[:lower:]] Letras minúsculas [az] |
8 | [[:print:]] Caracteres imprimibles (caracteres sin control) |
9 | [[:punct:]] Caracteres de puntuación |
10 | [[:space:]] Espacio en blanco |
11 | [[:upper:]] Letras mayúsculas [AZ] |
12 | [[:xdigit:]] Dígitos hexadecimales [0-9 af AF] |
Aampersand referencias
los sed metacharacter &representa el contenido del patrón que se emparejó. Por ejemplo, digamos que tiene un archivo llamadophone.txt lleno de números de teléfono, como los siguientes:
5555551212
5555551213
5555551214
6665551215
6665551216
7775551217
Quieres hacer el area code(los primeros tres dígitos) entre paréntesis para facilitar la lectura. Para hacer esto, puede usar el carácter de reemplazo comercial:
$ sed -e 's/^[[:digit:]][[:digit:]][[:digit:]]/(&)/g' phone.txt
(555)5551212
(555)5551213
(555)5551214
(666)5551215
(666)5551216
(777)5551217
Aquí, en la parte del patrón, está haciendo coincidir los primeros 3 dígitos y luego usando & está reemplazando esos 3 dígitos con los alrededores parentheses.
Usando múltiples comandos sed
Puede usar varios comandos sed en un solo comando sed de la siguiente manera:
$ sed -e 'command1' -e 'command2' ... -e 'commandN' files
aquí command1 mediante commandNson comandos sed del tipo discutido anteriormente. Estos comandos se aplican a cada una de las líneas en la lista de archivos dada por archivos.
Usando el mismo mecanismo, podemos escribir el ejemplo de número de teléfono anterior de la siguiente manera:
$ sed -e 's/^[[:digit:]]\{3\}/(&)/g' \
-e 's/)[[:digit:]]\{3\}/&-/g' phone.txt
(555)555-1212
(555)555-1213
(555)555-1214
(666)555-1215
(666)555-1216
(777)555-1217
Note - En el ejemplo anterior, en lugar de repetir la palabra clave de clase de carácter [[:digit:]] tres veces, lo reemplazamos con \{3\}, lo que significa que la expresión regular anterior coincide tres veces. También hemos utilizado\ para dar un salto de línea y esto debe eliminarse antes de ejecutar el comando.
Volver Referencias
los ampersand metacharacteres útil, pero aún más útil es la capacidad de definir regiones específicas en expresiones regulares. Estas regiones especiales se pueden utilizar como referencia en sus cadenas de reemplazo. Al definir partes específicas de una expresión regular, puede volver a referirse a esas partes con un carácter de referencia especial.
Que hacer back references, primero debe definir una región y luego volver a referirse a esa región. Para definir una región, insertabackslashed parenthesesalrededor de cada región de interés. La primera región que rodea con barras diagonales inversas se hace referencia a\1, la segunda región por \2, y así.
Asumiendo phone.txt tiene el siguiente texto:
(555)555-1212
(555)555-1213
(555)555-1214
(666)555-1215
(666)555-1216
(777)555-1217
Prueba el siguiente comando:
$ cat phone.txt | sed 's/\(.*)\)\(.*-\)\(.*$\)/Area \
code: \1 Second: \2 Third: \3/'
Area code: (555) Second: 555- Third: 1212
Area code: (555) Second: 555- Third: 1213
Area code: (555) Second: 555- Third: 1214
Area code: (666) Second: 555- Third: 1215
Area code: (666) Second: 555- Third: 1216
Area code: (777) Second: 555- Third: 1217
Note - En el ejemplo anterior, cada expresión regular dentro del paréntesis sería referenciada por \1, \2y así. Hemos usado\para dar salto de línea aquí. Esto debe eliminarse antes de ejecutar el comando.