Grep es sin duda alguna no de los comandos más utilizados en el día a día por los administradores de sistemas. Muchos no van más allá de sus usos más básicos, que si bien cumplen a la perfección su función son una mínima parte de las posibilidades que nos ofrece. Algunos de estos ejemplos se pueden ejecutar tanto con grep como con egrep (egrep= grep -E), independientemente de que casi siempre se ejecuten con egrep en el post. Espero que os sean de utilidad.
Este es el texto que se va a utilizar para trabajar como ejemplo. Sí, es un fichero de configuración de un Cluster MySQL de prueba, pero es que no tenía otra cosa a mano y no me apetecía preparar un fichero específicamente para esto ;)
[ndb_mgmd] hostname=192.168.0.10 # Hostname or IP address of management node datadir=/var/lib/mysql-cluster # Directory for management node log files # Options for data node "A": [ndbd] # (one [ndbd] section per data node) hostname=192.168.0.30 # Hostname or IP address datadir=/usr/local/mysql/data # Directory for this data node's data files # Options for data node "B": [ndbd] hostname=192.168.0.40 # Hostname or IP address datadir=/usr/local/mysql/data # Directory for this data node's data files # SQL node options: [mysqld] hostname=192.168.0.20 # Hostname or IP address # (additional mysqld connections can be # specified for this node for various # purposes such as running ndb_restore)
Buscar dos ó n strings distintas dentro de un mismo fichero
La sintaxis es ‘(cadena1|cadena2|cadenaN)’. La salida será todas aquellas líneas que contienen cualquiera de esas strings. Esto nos permite hacer múltiples búsquedas en un único comando:
$ egrep '(192.168.0.30|192.168.0.40)' test hostname=192.168.0.30 # Hostname or IP address hostname=192.168.0.40 # Hostname or IP address
$ egrep '(192.168.0.30|192.168.0.40|192.168.0.20)' test hostname=192.168.0.30 # Hostname or IP address hostname=192.168.0.40 # Hostname or IP address hostname=192.168.0.20 # Hostname or IP address
Usar los corchetes para reducir el rango de búsqueda
Podemos hacer uso de los corchetes [] para definir, dentro de una misma string, que una sección contenga únicamente X carácteres, un rango de ellos, etc.
En este caso queremos sacar únicamente los resultados que contengan 192.168.0.30 y 192.168.0.40:
$ egrep 192.168.0.[30,40] test hostname=192.168.0.30 # Hostname or IP address hostname=192.168.0.40 # Hostname or IP address
Pero si quisiéramos definir los rangos que queremos mostrar para los dos últimos caracteres, en este caso numéricos (se podría hacer con alfanuméricos) podemos hacerlo separando el valor inicial y el final con «-«. En este ejemplo queremos que nos muestre aquello que cumpla la condición de que el primer número del último bloque tiene que ser 0,1 ó 2:
$ egrep 192.168.0.[0-2]0 test hostname=192.168.0.10 # Hostname or IP address of management node hostname=192.168.0.20 # Hostname or IP address
Y en este que el primer número del último bloque sea 1,2 ó 3 y el último entre 0 y 9:
$ egrep 192.168.0.[0-3][0-9] test hostname=192.168.0.10 # Hostname or IP address of management node hostname=192.168.0.30 # Hostname or IP address hostname=192.168.0.20 # Hostname or IP address
Un ejemplo práctico con caracteres alfanuméricos sería usar por ejemplo [a-c]test, que buscaría atest, btest y ctest ó por ejemplo [ar4d]test que buscaría atest, rtest, 4test y dtest.
Uso de clases predefinidas
Existen clases predefinidas que nos pueden llegar a ahorrar mucho trabajo. Son las siguientes:
[:alnum:], [:alpha:], [:cntrl:], [:digit:], [:graph:], [:lower:], [:print:], [:punct:], [:space:], [:upper:], [:xdigit:]
Lo que hace cada una de ellas está claro por su nombre, no obstante vamos a ver un ejemplo. Podemos buscar toda línea que contenga un carácter en mayúsculas:
$ egrep [[:upper:]] test hostname=192.168.0.10 # Hostname or IP address of management node datadir=/var/lib/mysql-cluster # Directory for management node log files ... ...
Todo lo que comienza o termina por…
Esto es sencillo, las líneas comienzan por el carácter ^ y terminan con $. Por lo que:
Buscar todo lo que comience por «hostname»:
$ egrep ^hostname test hostname=192.168.0.10 # Hostname or IP address of management node hostname=192.168.0.30 # Hostname or IP address hostname=192.168.0.40 # Hostname or IP address hostname=192.168.0.20 # Hostname or IP address
O todo lo que termine por «node»:
$ egrep node$ test hostname=192.168.0.10 # Hostname or IP address of management node
Más expresiones regulares
Ya hicimos un artículo sobre ello hace tiempo, podéis revisarlo aquí: unix: Expresiones regulares, ahí también encontraréis unos cuantos ejemplos de grep. Son muy útiles los operadores de repetición:
? El carácter que precede es opcional y coincide al menos una vez. * El carácter que precede coincidirá 0 o más veces. + El carácter que precede coincidirá 1 o más veces. {n} El carácter que precede coincidirá exactamente n veces. {n,} El carácter que precede coincidirá n o más veces. {,m} El carácter que precede coincidirá como máximo m veces. {n,m} El carácter que precede coincidirá entre n y m veces.
Podemos entonces buscar todas las líneas del fichero que contienen una IP. Usamos primero los corchetes para definir que puede haber números del 0 al 9, con las llaves decimos que habrá 1 o 3 números en cada bloque y así cuatro veces (nota: hay que escapar las llaves):
$ grep '[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}' test hostname=192.168.0.10 # Hostname or IP address of management node hostname=192.168.0.30 # Hostname or IP address hostname=192.168.0.40 # Hostname or IP address hostname=192.168.0.20 # Hostname or IP address
Buscar palabras completas, contar resultados
Para indicar a grep que queremos que la búsqueda se centre en palabras y no en caracteres sueltos especificamos el parámetro «-w». Podemos ver la diferencia buscando «data» en el ejemplo, contamos los resultados satisfactorios con el parámetro «-c»:
$ grep -cw data test 5 $ grep -c data test 6
Excluir resultados, sensibilidad a mayúsculas
Algo básico a la hora de usar grep es conocer los parámetros «-v» que excluye la cadena indicada en el resultado y «-i» que especifica que no se tendrá en cuenta si el resultado es mayúscula o minúscula.
Eliminamos las líneas que tienen comodines:
$ grep -v "#" test [ndb_mgmd] [ndbd] [ndbd] [mysqld]
Uso de pipes
Todos usamos pipes (|) para acotar resultados. Hacemos un primer grep, con el resultado de ese hacemos otro y así sucesivamente:
$ grep -iw hostname test | grep 192.168.0.[0-9]0 | grep -v 192.168.0.40 | grep -vw node hostname=192.168.0.30 # Hostname or IP address hostname=192.168.0.20 # Hostname or IP address
Listar los archivos que contienen la cadena
Con el parámetro -l podemos ejecutar grep contra varios archivos (y de forma recursiva en múltiples directorios con -R) y recibiremos el listado de archivos con coincidencias sin mostrar las líneas que contienen la cadena:
$ grep -lR SQL * config.ini header.xcf iptables.sh test dir1/test.sql dir2/prueba.txt ...
Número de línea en la que se encuentran los resultados
Para saber el número de línea en la que se encuentra el resultado utilizaremos el parámetro -n:
$ grep -n hostname test 2:hostname=192.168.0.10 # Hostname or IP address of management node 8:hostname=192.168.0.30 # Hostname or IP address ...
Cuantas veces se encuentran resultados
Si «-n» nos monstraba el nº de línea en el que estaba la coincidencia, «-c» nos dice cuantas veces está la búsqueda en el fichero:
$ grep -c hostname test 4
Bueno, de momento esto es todo. Por supuesto hay muchas más opciones y explotar la potencia de grep llevaría mucho tiempo así que a partir de aquí investigáis vosotros ;)
muy buenos ejemplos para aplicar rápidamente
1. ls /dev/t???[1-4]
2. cd $HOME
pwd
3. mkdir PRACTICA
4. mkdir PRACTICA/P1 PRACTICA/P2 PRACTICA/P1/P11
5. NANO PRACTICA/P1/F1.TXT.
6. cd /usr/include
ls *.h | tee /home/aranda/PRACTICA/P1/lista_ficheros.txt 2> /home/aranda/PRACTICA/P1/malos.txt
8. sudo find /etc -name ‘*.conf’ > /home/aranda/practica/p1/lista_ficheros.txt
9.grep -n error /var/log/syslog
grep -c error /var/log/syslog
10. grep Est PRACTICA/P1/f1
11. grep ‘[$]’ Practica/P1/F1.txt
12. tr -d [a-z] PRACTICA/P1/F2.txt
13. tr -s [0-9] PRACTICA/P1/F3.txt
14.find /home/aranda -maxdepth 3 | tee /home/aranda Practica/P1/carpetas.txt
15. sort -k3 -u PRACTICA/P1/F1.txt
16. tail -20 /etc/rsyslog.conf
17.useradd prueba1
useradd prueba2
useradd prueba3
groupadd testeadores
gpasswd -a prueba1 testeadores
gpasswd -a prueba2 testeadores
18.groupmod -n pruebas testeadores
19. date -d «+3 days» + «%A, %d de %B %Y»
20.diff PRACTICA/P1/F1.txt PRACTICA/P1/F2.txt
Simplemente espectacular!! gracias
alguien podra ayudarme , necesito diferenciar si una cadena tiene numeros y/o letras hace cierto procesos y si tiene caracteres especiales indique que necesitas ingresar caracteres especiales
case $pas in
[:alnum:]) echo “ $pas Ha introducido letras o numeros”;;
[!-~]) echo “ $pas Necesitas ingresar passwords alfanumerico ” ;;
esac
lo he intentado con [a-z,A-Z] y con *) respectivamente, solo me reconoce si ingreso una letra pero si ingreso varias letras me dice que necesito ingresar password alfanumerico, espero comentarios
Hola!
Estoy intentando usar la funcionalidad de buscar números [0-9] en bloques \{1,3\}, pero en lugar de decirle que quiero que los bloques sean de 1 o de 3 números como arriba, quiero que los bloques sean de 1 a 9 números. He probado con [0-9]\{1-9\}, y con [0-9]\{1,2,3,4,5,6,7,8,9\}, pero obtengo el siguiente error:
egrep: invalid repetition count(s)
¿Cómo podría implementar esto? Muchas gracias de antemano
Aitor