Búsqueda de sitios web

Cómo utilizar Select-String equivalente a PowerShell Grep


Cuando necesite buscar en una cadena o archivos de registro en Linux, podemos usar el comando grep. Para PowerShell, podemos usar el equivalente grep Select-String. Podemos obtener prácticamente los mismos resultados con este potente cmdlet.

Select-String utiliza expresiones regulares similares a grep para encontrar patrones de texto en archivos y cadenas. Puede buscar en varios archivos e informar la ubicación, incluido el número de línea de la cadena de cada archivo. También es posible encontrar solo la primera aparición de una cadena o, por ejemplo, devolver solo los archivos que no coinciden con una cadena.

En este artículo, veremos el equivalente grep de PowerShell Select-String. Vamos a ver diferentes ejemplos que puedes usar para encontrar una cadena con PowerShell. ¡Asegúrate de leer hasta el final para obtener un pequeño consejo adicional!

Encontrar una cadena con PowerShell Select-String

Antes de profundizar en todas las posibilidades del cmdlet select-string, primero echemos un vistazo a un par de ejemplos comunes. Para buscar una cadena particular en los archivos de registro podemos usar el siguiente cmdlet en PowerShell:

# Search for the string error in the path
Select-String -Pattern "error" -Path "C:\temp\log\*.log"

# or in short:
Select-String "error" "C:\temp\log\*.log"

El equivalente grep sería:

grep "error" .\log\*.log

De forma predeterminada, la salida del cmdlet select-string mostrará el nombre del archivo, el número de línea y la línea completa donde se encontró la cadena:

La ventaja de PowerShell es que podemos formatear fácilmente la salida en un formato más legible. Si, por ejemplo, solo está interesado en el nombre del archivo, la ruta y el número de línea, puede formatear los resultados en una tabla y seleccionar solo los campos que necesita:

Select-String -Pattern "error" -Path "C:\temp\log\*.log" | Select LineNumber, FileName, Path

# Result:
LineNumber Filename         Path
---------- --------         ----
         9 01032022-app.log C:\temp\log\01032022-app.log
        18 04032022-app.log C:\temp\log\04032022-app.log
         7 05032022-app.log C:\temp\log\05032022-app.log
         9 11022022-app.log C:\temp\log\11022022-app.log
         9 11032021-app.log C:\temp\log\11032021-app.log
         9 11102021-app.log C:\temp\log\11102021-app.log
        38 11102021-app.log C:\temp\log\11102021-app.log
         9 15032022-app.log C:\temp\log\15032022-app.log

Parámetros de cadena de selección

Así que hemos echado un vistazo rápido al uso básico del cmdlet, ahora profundicemos un poco más en todas las posibilidades del cmdlet de cadena de búsqueda en PowerShell. El cmdlet viene con un par de parámetros que nos ayudarán a buscar cadenas y seleccionar los resultados:

-Pattern

El texto o cadena a buscar. Acepta una expresión regular

-Path

Especifique el archivo o la ruta a los archivos para buscar. Acepta comodines

-CaseSensitive

La cadena de búsqueda distingue entre mayúsculas y minúsculas

-Context

Mostrar líneas antes y/o después del patrón.

-Quiet

Solo devuelve verdadero o falso

-Raw

Devuelve sólo la cadena coincidente como grep

-List

Enumere solo la primera coincidencia en los archivos. Se utiliza para obtener una lista de archivos con patrón.

-SimpleMatch

Trate el patrón como una simple cuerda.

-Include

Especifica los archivos que se incluirán en la búsqueda (“*.txt”,”*.log”)

-Exclude

Especifica archivos para excluir de la ruta de búsqueda.

-NotMatch

Devolver sólo los artículos que no coincidan con el patrón.

-AllMatches

Devuelve todas las coincidencias del resultado.

Mostrando líneas antes y después con Contexto

El cmdlet Select-String devuelve la línea donde encontró la cadena que buscamos. Pero al buscar en archivos de registro, por ejemplo, probablemente también desee saber qué sucedió antes o después del error.

Aquí es donde entra en juego el parámetro -context. Le permite especificar el número de líneas que deben devolverse para y/o después de la línea coincidente. El primer dígito es el número de líneas antes, el segundo es el número de líneas después. Si solo proporciona un dígito, se utilizará para ambos.

# Return 3 lines before
Select-String -Pattern "error" -Path "C:\temp\log\sub\*.log" -Context 3,0

# Return 2 lines before and 2 lines after the error:
Select-String -Pattern "error" -Path "C:\temp\log\sub\*.log" -Context 2

La línea que coincidió con el patrón se indica con > y la cadena está resaltada:

Devuelve verdadero o falso con silencio

Cuando se utiliza la cadena de selección equivalente a grep de PowerShell dentro de un script, a veces solo necesita saber si la cadena existe o no. De forma predeterminada, el cmdlet devolverá un objeto MatchInfo. Un objeto con el número de línea, ruta, cadena, etc.

Para comprobar si los archivos de registro contienen algún error o no podemos hacer lo siguiente:

# Returns true or False
Select-String -Pattern "error" -Path "C:\temp\log\sub\*.log" -Quiet

# Result:
True

Devuelve sólo la cadena coincidente con Raw

Si está acostumbrado al comando grep de Linux, habrá notado que el resultado de select-string es ligeramente diferente. El equivalente de PowerShell devuelve un objeto, en lugar de solo la cadena que devuelve el comando grep.

Cuando agrega el parámetro -raw a su comando, el cmdlet solo devolverá la cadena que coincidió con el patrón:

Select-String -Pattern "error" -Path "C:\temp\log\sub\*.log" -Raw

# Result:
2022-03-01 10:59:21 [ERROR] - String failed to be a string

Buscar entre múltiples tipos de archivos

El parámetro de ruta ya acepta comodines, lo que nos permite buscar en varios archivos. Pero en este caso, sólo podemos buscar en un tipo de archivo. Al utilizar el parámetro -include podemos especificar varios tipos de archivos en los que queremos buscar.

Para usar el parámetro, aún debemos proporcionar la ruta; de lo contrario, el cmdlet buscará en la ubicación raíz del script.

# Search in the txt and log files
Select-String -Pattern "error" -Path "C:\temp\log\sub\*" -Include "*.txt","*.log"

# Result
C:\temp\log\sub\LT3452-process.log:4:2022-03-01 10:59:21 [ERROR] - String failed to be a string
C:\temp\log\sub\LT4423-process.txt:3:2022-02-01 05:49:21 [ERROR] - Squirrel failed to find process

También es posible excluir extensiones de archivo con el parámetro -exclude.

Enumere solo los archivos con Select-String

Al buscar en varios archivos con el cmdlet select-string, PowerShell devolverá todas las instancias de la cadena que ha encontrado. Pero a veces sólo desea saber si un archivo de registro, por ejemplo, contiene un error.

Si buscamos en los archivos de registro el error de patrón, podemos ver que el archivo 11102021-app.log se encuentra dos veces:

Select-String -Pattern "error" -Path "C:\temp\log\*" | Select LineNumber, Filename

# Result:
LineNumber Filename
---------- --------
         9 01032022-app.log
        18 04032022-app.log
         7 05032022-app.log
         9 11022022-app.log
         9 11032021-app.log
         9 11102021-app.log
        38 11102021-app.log
         9 15032022-app.log

Al utilizar el parámetro -List solo se devuelven las primeras instancias, lo que da como resultado una lista única de nombres de archivos que contienen el patrón coincidente:

Select-String -Pattern "error" -Path "C:\temp\log\*" -List | Select LineNumber, Filename

Líneas de retorno sin patrón.

Todo este tiempo hemos estado buscando cadenas dentro de archivos de registro que contengan la cadena "error". ¿Pero qué pasa si quieres conseguir lo contrario? ¿Todas las líneas que no contienen la palabra “error”?

Para esto, podemos usar el parámetro -NotMatch. Esto devolverá todas las líneas en la ruta que no coincidan con el patrón que hemos proporcionado:

Select-String -Pattern "error" -Path "C:\temp\log\*" -NotMatch | Select LineNumber, Filename

Buscar archivos que no coincidan con el patrón

El cmdlet Select-String busca en el nivel de línea a través de archivos. Esto significa que no podemos simplemente usar este cmdlet para devolver solo los archivos que no contienen una cadena en particular.

Para obtener todos los archivos que no contienen la cadena, necesitaremos usar el cmdlet Get-ChildItem y usar el cmdlet Select-String en cada archivo.

Al usar el parámetro -quiet podemos devolver verdadero o falso, lo que nos permite seleccionar (y devolver) solo los archivos que no contienen el patrón:

Get-ChildItem -path "C:\temp\log\*" | Where-Object { !( $_ | Select-String -Pattern "error" -Quiet ) }

# Result:

    Directory: C:\temp\log

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           15-3-2022    13:52                sub
-a---           15-3-2022    14:09           4120 04032022-app.log
-a---           15-3-2022    12:59           2860 11032022-app.log

PowerShell Select-String recursivo

El cmdlet select-string en PowerShell solo busca en el directorio indicado. No recorrerá las subcarpetas, incluso si usa comodines. Para buscar también en todas las subcarpetas, necesitaremos combinar el cmdlet con Get-ChildItem.

Entonces, para buscar en todas las subcarpetas, primero obtendremos todos los elementos con Get-Childitem usando el parámetro -Recurse para buscar de forma recursiva. Y luego pase cada archivo al cmdlet Select-String:

Get-ChildItem -path "C:\temp\log\*" -Recurse | Select-String -Pattern "error" | Select LineNumber, Filename, Path

PowerShell Select-String Múltiples patrones

Al buscar en archivos de registro de otros archivos de texto, a veces es necesario buscar varios patrones. Ahora podría simplemente ejecutar el cmdlet Select-String dos veces, pero eso no es realmente eficiente.

Afortunadamente, podemos proporcionar múltiples patrones al cmdlet Select-String. Simplemente puede crear una matriz con cadenas o cadenas separadas por comas:

Select-String -Pattern "error","warning" -Path "C:\temp\log\*" -List | Select LineNumber, Filename, Pattern

Como puede ver, agregué la propiedad Patrón a la declaración de selección. De esta forma podemos ver qué patrón tiene coincidencias en el archivo y en qué línea.

Concluyendo

Select-String, equivalente a grep de PowerShell, es una gran herramienta para buscar cadenas dentro de archivos de texto u otros flujos de salida. Si realmente te gusta usar el comando grep, tengo un pequeño consejo para ti. Puede crear un nuevo alias en PowerShell para que se use el cmdlet select-string cuando escriba grep.

Para crear el tipo de alias:

new-alias grep select-string

Ahora puedes usar grep como en Linux:

Espero que este artículo te haya resultado útil. Si tienes alguna pregunta, deja un comentario a continuación.

Artículos relacionados