GNU/Linux >> Tutoriales Linux >  >> Linux

10 ejemplos prácticos de comandos Grep para desarrolladores

Recientemente, comencé a trabajar con Asciidoctor.js y en el proyecto Asciidoctor.js-pug y Asciidoctor-templates.js.

No siempre es fácil ser efectivo de inmediato cuando profundiza por primera vez en un código base que contiene varios miles de líneas. Pero mi arma secreta para encontrar mi camino a través de tantas líneas de código es el grep herramienta.

Voy a compartir con ustedes cómo usar el comando grep en Linux con ejemplos.

Ejemplos utiles en la vida real de los comandos grep en Linux

Si miras al man , verá esa breve descripción para el grep herramienta:“imprimir líneas que coincidan con un patrón.”

Sin embargo, no se deje engañar por una definición tan humilde:grep es una de las herramientas más útiles en la caja de herramientas de Unix y hay innumerables ocasiones para usarla tan pronto como trabaje con archivos de texto.

Siempre es mejor tener ejemplos del mundo real para aprender cómo funcionan las cosas. Entonces, usaré el árbol fuente de Asciidoctor.js para ilustrar algunos de los grep capacidades.

Puede descargar ese árbol de fuentes de GitHub y, si lo desea, incluso puede consultar el mismo conjunto de cambios que utilicé al escribir este artículo. Eso asegurará que obtenga resultados perfectamente idénticos a los descritos en el resto de este artículo:

git clone https://github.com/asciidoctor/asciidoctor.js
cd asciidoctor.js
git checkout v1.5.6-rc.1

1. Encuentra todas las apariciones de una cadena (uso básico)

Asciidoctor.js admite el motor Nashorn JavaScript para la plataforma Java. No conozco a Nashorn, así que podría aprovechar la oportunidad para aprender más al explorar las partes del proyecto que hacen referencia a ese motor de JavaScript.

Como punto de partida, verifiqué si había alguna configuración relacionada con Nashorn en el package.json archivo que describe las dependencias del proyecto:

[email protected]:~$ grep nashorn package.json
    "test": "node npm/test/builder.js && node npm/test/unsupported-features.js && node npm/test/jasmine-browser.js && node npm/test/jasmine-browser-min.js && node npm/test/jasmine-node.js && node npm/test/jasmine-webpack.js && npm run test:karmaBrowserify && npm run test:karmaRequirejs && node npm/test/nashorn.js",

Sí, aparentemente hubo algunas pruebas específicas de Nashorn. Entonces, investiguemos eso un poco más.

2. Búsqueda insensible a mayúsculas y minúsculas en un conjunto de archivos

Ahora, quiero echar un vistazo más de cerca a los archivos de ./npm/test/ directorio mencionando explícitamente a Nashorn.

Una búsqueda que no distingue entre mayúsculas y minúsculas (-i opción) es probablemente mejor aquí ya que necesito encontrar ambas referencias a nashorn y Nashorn (o cualquier otra combinación de caracteres en mayúsculas y minúsculas):

[email protected]:~$ grep -i nashorn npm/test/*.js
npm/test/nashorn.js:const nashornModule = require('../module/nashorn');
npm/test/nashorn.js:log.task('Nashorn');
npm/test/nashorn.js:nashornModule.nashornRun('jdk1.8.0');

De hecho, la insensibilidad a mayúsculas y minúsculas fue útil aquí. De lo contrario, me habría perdido require('../module/nashorn') declaración. Sin duda, debería examinar ese archivo con mayor detalle más adelante.

3. Encuentra todos los archivos que no coinciden

Por cierto, ¿hay algunos archivos específicos que no sean de Nashorm en npm/test/? ¿directorio? Para responder a esa pregunta, podemos usar la opción "imprimir archivos que no coinciden" de grep (-L opción):

sh$ grep -iL nashorn npm/test/*
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js

Observe cómo con -L opción la salida de grep ha cambiado para mostrar solo los nombres de archivo. Por lo tanto, ninguno de los archivos anteriores contiene la cadena "nashorn" (independientemente del caso). Eso no significa que no estén relacionados de alguna manera con esa tecnología, pero al menos, las letras "n-a-s-h-o-r-n" no están presentes.

4. Encontrar patrones en archivos ocultos y recursivamente en subdirectorios

Los últimos dos comandos usaron un patrón global de shell para pasar la lista de archivos a examinar al grep dominio.

Sin embargo, esto tiene algunas limitaciones inherentes:la estrella (* ) no coincidirá con los archivos ocultos. Tampoco coincidirá con archivos (eventualmente) contenidos en subdirectorios.

Una solución sería combinar grep con el comando de búsqueda en lugar de confiar en un patrón global de shell:

# This is not efficient as it will spawn a new grep process for each file
[email protected]:~$ find npm/test/ -type f -exec grep -iL nashorn \{} \;
# This may have issues with filenames containing space-like characters
[email protected]:~$ grep -iL nashorn $(find npm/test/ -type f)

Como lo mencioné como comentario en el bloque de código anterior, cada una de estas soluciones tiene inconvenientes.

Con respecto a los nombres de archivo que contienen caracteres similares a espacios, te dejo investigar el grep -z opción que, combinada con -print0 opción de find comando, puede mitigar ese problema. ¡No dudes en usar la sección de comentarios al final de este artículo para compartir tus ideas sobre ese tema!

Sin embargo, una mejor solución sería usar el "recursivo" (-r ) opción de grep . Con esa opción, proporciona en la línea de comando la raíz de su árbol de búsqueda (el directorio de inicio) en lugar de la lista explícita de nombres de archivo para examinar.

Con el -r opción, grep buscará todos los archivos en el directorio especificado, incluidos los ocultos, y luego descenderá recursivamente a cualquier subdirectorio:

[email protected]:~$ grep -irL nashorn npm/test/npm/
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js

En realidad, con esa opción, también podría comenzar mi exploración un nivel más arriba para ver si hay pruebas que no son npm que también se dirigen a Nashorn:

[email protected]:~$ grep -irL nashorn npm/

Te dejo probar ese comando por ti mismo para ver su resultado; pero como pista, ¡puedo decir que debería encontrar muchos más archivos coincidentes!

5. Filtrado de archivos por su nombre (usando expresiones regulares)

Entonces, parece haber algunas pruebas específicas de Nashorn en ese proyecto. Dado que Nashorn es Java, otra pregunta que podría plantearse sería “¿Hay algunos archivos fuente de Java en el proyecto que mencionen explícitamente a Nashorn?” .

Dependiendo de la versión de grep utiliza, hay al menos dos soluciones para responder a esa pregunta.

El primero es usar grep para encontrar todos los archivos que contienen el patrón "nashorn", luego canalice la salida de ese primer comando a un segundo grep instancia filtrando archivos de origen que no son de Java:

[email protected]:~$ grep -ir nashorn ./ | grep "^[^:]*\.java"
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/basic.js"));

La primera mitad del comando debería ser comprensible ahora. Pero, ¿qué pasa con esa parte "^[\^:]*\\.java"?

A menos que especifique el -F opción, grep asume que el patrón de búsqueda es una expresión regular. Eso significa que, además de los caracteres simples que coincidirán literalmente, tiene acceso a un conjunto de metacaracteres para describir patrones más complejos. El patrón que usé arriba solo coincidirá con:

  • ^ el comienzo de la línea
  • [^:]* seguido de una secuencia de cualquier carácter excepto dos puntos
  • \. seguido de un punto (el punto tiene un significado especial en regex , así que tuve que protegerlo con una barra invertida para expresar que quiero una coincidencia literal)
  • java y seguido de las cuatro letras "java".

En la práctica, desde grep usaré dos puntos para separar el nombre del archivo del contexto, mantengo solo las líneas que tienen .java en la sección de nombre de archivo. Vale la pena mencionarlo sería coincide también con .javascript nombres de archivo Esto es algo que dejo que intentes resolver por ti mismo si quieres.

6. Filtrado de archivos por su nombre usando grep

Las expresiones regulares son extremadamente poderosas. Sin embargo, en ese caso particular, parece excesivo. Sin mencionar que con la solución anterior, dedicamos tiempo a examinar todos los archivos en busca del patrón "nashorn", la mayoría de los resultados se descartan en el segundo paso de la canalización.

Si está utilizando la versión GNU de grep , algo que es probable si está utilizando Linux, tiene otra solución con --include opción. Esto instruye a grep para buscar solo en archivos cuyo nombre coincida con el patrón global dado:

[email protected]:~$ grep -ir nashorn ./ --include='*.java'
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/basic.js"));

7. Encontrar palabras

Lo interesante del proyecto Asciidoctor.js es que es un proyecto multilenguaje. En esencia, Asciidoctor está escrito en Ruby, por lo que, para que se pueda utilizar en el mundo de JavaScript, debe "transpilarse" utilizando Opal, un compilador de fuente a fuente de Ruby a JavaScript. Otra tecnología que no conocía antes.

Entonces, después de haber examinado las especificidades de Nashorn, me asigné la tarea de comprender mejor la API de Opal. Como primer paso en esa búsqueda, busqué todas las menciones del Opal objeto global en los archivos JavaScript del proyecto. Puede aparecer en afectaciones (Opal = ), acceso de miembro (Opal. ) o tal vez incluso en otros contextos. Una expresión regular haría el truco. Sin embargo, una vez más, grep tiene una solución más ligera para resolver ese caso de uso común. Usando el -w opción, solo coincidirá con palabras , es decir, patrones precedidos y seguidos por un carácter que no es una palabra. Un carácter que no es una palabra es el comienzo de la línea, el final de la línea o cualquier carácter que no sea ni una letra, ni un dígito, ni un guión bajo:

[email protected]:~$ grep -irw --include='*.js' Opal .
...

8. coloreando la salida

No copié la salida del comando anterior ya que hay muchas coincidencias. Cuando la salida es tan densa, es posible que desee agregar un poco de color para facilitar la comprensión. Si esto aún no está configurado de manera predeterminada en su sistema, puede activar esa característica usando GNU --color opción:

[email protected]:~$ grep -irw --color=auto --include='*.js' Opal .
...

Debería obtener el mismo resultado largo que antes, pero esta vez la cadena de búsqueda debería aparecer en color si aún no era el caso.

9. Contando líneas coincidentes o archivos coincidentes

Mencioné dos veces que la salida de los comandos anteriores era muy larga. ¿Cuánto tiempo exactamente?

[email protected]:~$ grep -irw --include='*.js' Opal . | wc -l
86

Eso significa que tenemos un total 86 líneas coincidentes en todas los expedientes examinados. Sin embargo, ¿cuántos archivos diferentes coinciden? Con el -l opción puede limitar el grep generar los archivos coincidentes en lugar de mostrar líneas coincidentes . Entonces ese simple cambio dirá cuántos archivos coinciden:

[email protected]:~$ grep -irwl --include='*.js' Opal . | wc -l
20

Si eso te recuerda el -L opción, no es de extrañar:como es relativamente común, se usan minúsculas/mayúsculas para distinguir opciones complementarias. -l muestra los nombres de archivo coincidentes. -L muestra nombres de archivos que no coinciden. Para otro ejemplo, te dejo consultar el manual para el -h /-H opciones.

Cerremos ese paréntesis y volvamos a nuestros resultados:86 líneas coincidentes. 20 archivos coincidentes. Sin embargo, ¿cómo se distribuyen las líneas coincidentes? en los archivos coincidentes ? Podemos saber que usando -c opción de grep que contará el número de líneas coincidentes por archivo examinado (incluidos los archivos con cero coincidencias):

[email protected]:~$ grep -irwc --include='*.js' Opal .
...

A menudo, esa salida necesita un procesamiento posterior, ya que muestra sus resultados en el orden en que se examinaron los archivos, y también incluye archivos sin ninguna coincidencia, algo que generalmente no nos interesa. Esto último es bastante fácil de resolver:

[email protected]:~$ grep -irwc --include='*.js' Opal . | grep -v ':0$'

En cuanto a ordenar cosas, puede agregar el comando ordenar al final de la canalización:

[email protected]:~$ grep -irwc --include='*.js' Opal . | grep -v ':0$' | sort -t: -k2n

Te dejo revisar el sort manual de comandos para conocer el significado exacto de las opciones que utilicé. ¡No olvides compartir tus hallazgos usando la sección de comentarios a continuación!

10. Encontrar la diferencia entre dos conjuntos coincidentes

Si recuerdas, hace unos comandos, busqué la palabra "Ópalo." Sin embargo, si busco en el mismo conjunto de archivos todas las apariciones de la cadena “Opal”, obtengo unas veinte respuestas más:

[email protected]:~$ grep -irw --include='*.js' Opal . | wc -l
86
[email protected]:~$ grep -ir --include='*.js' Opal . | wc -l
105

Encontrar la diferencia entre esos dos conjuntos sería interesante. Entonces, ¿qué son las líneas que contienen las cuatro letras "ópalo" seguidas, pero esas cuatro letras no forman una palabra completa?

Esto no es tan fácil de responder a esa pregunta. Porque el lo mismo la línea puede contener ambos la palabra Opal, así como alguna palabra más grande que contenga esas cuatro letras. Pero como primera aproximación, puede usar esa canalización:

[email protected]:~$ grep -ir --include='*.js' Opal . | grep -ivw Opal
./npm/examples.js:  const opalBuilder = OpalBuilder.create();
./npm/examples.js:  opalBuilder.appendPaths('build/asciidoctor/lib');
./npm/examples.js:  opalBuilder.appendPaths('lib');
...

Aparentemente, mi próxima parada sería investigar el opalBuilder objeto, pero eso será para otro día.

La ultima palabra

Por supuesto, no entenderá la organización de un proyecto, y mucho menos la arquitectura del código, simplemente emitiendo un par de grep comandos!

Sin embargo, encuentro ese comando inevitable para identificar puntos de referencia y puntos de partida al explorar una nueva base de código.

Entonces, espero que este artículo te haya ayudado a comprender el poder de grep comando y que lo agregará a su caja de herramientas. ¡Sin duda no te arrepentirás!


Linux
  1. Ejemplos de comandos DNF para principiantes

  2. 10 ejemplos prácticos del uso del comando scp

  3. Comando cp en Linux:7 ejemplos prácticos

  4. Comando de apagado de Linux:5 ejemplos prácticos

  5. Comando nslookup:7 ejemplos prácticos

12 ejemplos prácticos de In Command en Linux

Los 40 ejemplos de comandos Go para aspirantes a desarrolladores de Golang

15 ejemplos prácticos del comando Rsync en Linux

5 ejemplos prácticos de Tail Command en Linux

15 ejemplos prácticos de comandos Grep en Linux / UNIX

UNIX/Linux:7 ejemplos prácticos de comandos PS para el monitoreo de procesos