Uno dei primi comandi Linux che molti amministratori di sistema imparano è grep. Questo venerabile strumento è stato in giro per decenni ed è fondamentale per qualsiasi amministratore. Il nucleo di Grep è semplicemente la capacità di cercare un testo semplice per un modello RegEx. Grep può cercare file in una data directory o input in streaming per ottenere corrispondenze. Sapevate che PowerShell ha Grep? Beh…quasi.
PowerShell, essendo un linguaggio, è più di un semplice binario a scopo singolo. Pertanto, quali abilità incorporate esistono per cercare del testo semplice usando schemi RegEx, proprio come fa grep? In questo articolo esploreremo la miriade di modi per cercare del testo nei file usando PowerShell.
Esplorando il Select-String Cmdlet
Select-String
(il nostro PowerShell grep) lavora su linee di testo e per default cerca la prima corrispondenza in ogni linea e poi visualizza il nome del file, il numero di riga e il testo all’interno della linea corrispondente. Inoltre, Select-String
può lavorare con diverse codifiche di file, come il testo Unicode, utilizzando il byte-order-mark (BOM) per determinare il formato di codifica. Se la BOM manca, Select-String
assumerà che si tratti di un file UTF8.
Parametri di Select-String
-
AllMatches
– Normalmente,Select-String
cercherà solo la prima corrispondenza in ogni riga, usando questo parametro il cmdlet cercherà più di una corrispondenza. Un singolo oggettoMatchInfo
sarà ancora emesso per ogni riga, ma conterrà tutte le corrispondenze trovate. -
CaseSensitive
– Le corrispondenze non sono case-sensitive per impostazione predefinita, questo forza il cmdlet a cercare le corrispondenze che corrispondono esattamente al modello di input. -
Context
– Un parametro molto utile in quanto, è possibile definire il numero di righe prima e dopo la corrispondenza che verrà visualizzata. Aggiungendo questo parametro si modifica l’oggetto emessoMatchInfo
per includere una nuova proprietàContext
che contiene le righe specificate.
Si tenga presente che se si convoglia l’output di
Select-String
in un’altra chiamataSelect-String
, il contesto non sarà disponibile poiché si sta cercando solo sulla singola proprietà risultanteMatchInfo
line
.
-
Culture
– Usato con il parametroSimpleMatch
, questo specifica una cultura da abbinare al modello specificato. Questo include opzioni comeen-US
es
, ofr-FR
come esempi. Alcune altre opzioni utili sono le opzioniOrdinal
eInvariant
Ordinal
è per i confronti binari non linguistici eInvariant
è per i confronti indipendenti dalla cultura.
Questo parametro è stato introdotto in PowerShell 7 e non è disponibile nelle versioni precedenti. Tieni anche presente che questo userà la cultura corrente del sistema, per impostazione predefinita, che può essere trovata usando
Get-Culture
.
-
Encoding
– Specifica la codifica del file di destinazione da cercare, che di default èutf8NoBOM
.-
ascii
: Utilizza la codifica per il set di caratteri ASCII (7-bit). -
bigendianunicode
: Codifica in formato UTF-16 utilizzando l’ordine di byte big-endian. -
oem
: Utilizza la codifica predefinita per MS-DOS e programmi per console. -
unicode
: Codifica in formato UTF-16 utilizzando l’ordine byte little-endian. -
utf7
: Codifica in formato UTF-7. -
utf8
: Codifica in formato UTF-8. -
utf8BOM
: Codifica in formato UTF-8 con Byte Order Mark (BOM) -
utf8NoBOM
: Codifica in formato UTF-8 senza Byte Order Mark (BOM) -
utf32
: Codifica in formato UTF-32.
A partire da PowerShell Core 6.2, il parametro
Encoding
accetta anche ID numerici di pagine di codice registrate come1251
o nomi di stringhe comewindows-1251
. -
A partire da PowerShell Core 6.2, il parametro
Encoding
accetta anche ID numerici di pagine di codice registrate come1251
o nomi di stringhe comewindows-1251
.
-
Exclude
– Lavorando con il parametroPath
, escludere elementi specifici utilizzando un pattern, come*.txt
. -
Include
– Proprio come il parametroExclude
Include
includerà solo gli elementi specificati utilizzando uno schema, come*.log
. -
List
– Restituisce solo la prima istanza di testo corrispondente da ogni file di input. Questo è inteso come un modo veloce ed efficiente per recuperare un elenco di file che hanno contenuti corrispondenti. -
LiteralPath
– Questo dice aSelect-String
di usare i valori come input, invece di interpretare valori come*
come un carattere jolly. Se il percorso include caratteri di escape, racchiudili in virgolette singole per non fare alcuna interpretazione. -
NoEmphasis
– Invece di evidenziare la stringa a cui corrisponde il pattern, disabilita l’evidenziazione delle corrispondenze. Per impostazione predefinita, l’evidenziazione usa colori negativi basati sui colori del testo di sfondo. -
NotMatch
– Cerca il testo che non corrisponde allo schema specificato. -
Path
– Specifica il percorso dei file da cercare. I caratteri jolly sono permessi, ma non è possibile specificare solo una directory. L’impostazione predefinita è la directory locale. -
Pattern
– Il modello per cercare il contenuto o i file di input basato su RegEx. -
SimpleMatch
– Usa una semplice corrispondenza invece delle espressioni regolari. Poiché RegEx non viene utilizzata, l’oggettoMatchInfo
restituito non ha alcun valore nella proprietàMatches
. -
Raw
– Visualizza le stringhe corrispondenti, senza un oggettoMatchInfo
. Questo è il comportamento più simile agrep
e non la natura più orientata agli oggetti di PowerShell. -
Quiet
– Restituisce solo un$true
o$false
se il modello viene trovato.
Utilizzare PowerShell Grep err… Select-String
Ovviamente sapere come funzionano i parametri e le opzioni di una cmdlet non è proprio la stessa cosa che usarla in un ambiente di produzione. Immergiamoci negli esempi e vediamo come possiamo sfruttare Select-String
per facilitare la ricerca delle corrispondenze di testo.
Ci sono tre modi in cui possiamo usare Select-String
per trovare le corrispondenze.
- Inseriamo il testo quotato nel
Select-String
cmdlet, cioè facciamo lo streaming del testo. - Utilizzando il testo memorizzato in una variabile, passare la variabile al parametro
InputObject
. - Utilizzare il parametro
Path
per specificare i file in cui cercare il testo.
I file che stiamo usando per testare questo sono contenuti generati casualmente, ma dello stesso tipo che si trova spesso nei sistemi di produzione.
Semplice corrispondenza nei file
Partendo da un esempio molto semplice, cerchiamo Joe
in una manciata di file CSV.
Select-String -Path "Users\*.csv" -Pattern "Joe"
Come potete vedere, questo è abbastanza semplice, vediamo come Joe
è evidenziato sulla linea con il resto dei dati. Ma quali dati vengono effettivamente restituiti qui? Diamo un’occhiata a tutte le proprietà di una corrispondenza restituita.
Select-String -Path "Users\*.csv" -Pattern "Joe" | Select-Object * -First 1
Abbiamo un paio di proprietà che sono utili. In particolare il line
path
pattern
, e matches
. La maggior parte di ciò che vogliamo sapere è nella proprietà matches
.
Select-String -Path "Users\*.csv" -Pattern "Joe" | Select-Object -ExpandProperty Matches -First 1
Qui potete vedere come anche se abbiamo usato una semplice espressione, questa è ancora un’espressione RegEx e i successivi dettagli disponibili.
E se cercassimo diversi valori usando modelli separati da virgole? Questo è utile in quanto definisce effettivamente tre diversi pattern e non un valore RegEx complesso.
Select-String -Path "Users\*.csv" -Pattern "Joe","Marti","Jerry"
Si può vedere come questo sia il caso, se selezioniamo solo il filename
pattern
, e line
dalla nostra ricerca.
Select-String -Path "Users\*.csv" -Pattern "Joe","Marti","Jerry" | Select-Object FileName, Pattern, Line
Corrispondenza RegEx più complessa
Ora che abbiamo dimostrato alcuni dei metodi di corrispondenza più semplici, che ne dite di utilizzare RegEx per cercare effettivamente modelli più utili? I tre esempi qui sono alla ricerca di indirizzi e-mail, indirizzi IP e numeri di previdenza sociale (SSN). I modelli usati qui non sono l’unico modo per costruire una ricerca RegEx, e ci possono essere modi più semplici. PowerShell Grep (Select-String) è un cmdlet piuttosto avanzato.
Guardiamo se le email sono contenute nei nostri file. Utilizzando una corrispondenza RegEx un po’ complessa, come mostrato di seguito, dimostreremo di trovare queste corrispondenze.
Select-String -Path "Users\*.csv" -Pattern '\\b+\.{2,4}\b' | Select-Object -First 10
Ovviamente, potrebbe essere più preoccupante se ci fossero SSN inclusi in un file. Una partita molto semplice per questo sarebbe la seguente.
Select-String -Path "Users\*.csv" -Pattern '\d\d\d-\d\d-\d\d\d\d' | Select-Object -First 10
Finalmente, cosa succede se vogliamo cercare alcuni indirizzi IP nel nostro file? Usando un’altra espressione RegEx per cercare quel modello, si fa un lavoro veloce.
Select-String -Path "Users\*.csv" -Pattern '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b' | Select-Object -First 10
Un avvertimento su questa RegEx. Tecnicamente, questo corrisponderà a valori fino a 999.999.999.999
che è un IP non valido. Potete costruire espressioni RegEx più accurate che diventeranno più lunghe, ma è un compromesso a seconda di ciò che state cercando di fare.
Cercare con il contesto
Il contesto è molto utile nella risoluzione dei problemi, aiuta a spiegare cosa sta succedendo prima e dopo un evento. Per esempio, cerchiamo in un log di Apache e troviamo questo suspendedpage.cgi
testo.
Select-String -Path "Web\*.txt" -Pattern "suspendedpage.cgi" -Context 1 | Select-Object -First 1
Il >
semplice indica la linea corrispondente, e c’è una linea prima della corrispondenza e dopo la corrispondenza. In questo esempio, questo potrebbe dirci che il bot di Google stava cercando robots.txt
e purtroppo ha ricevuto invece un risultato suspendedpage.cgi
. Poi, è andato a provare la homepage e forse ha ottenuto lo stesso errore.
Cosa contiene esattamente la proprietà context
emessa dall’oggetto MatchInfo
? Se ci espandiamo su quella proprietà, potete vedere che c’è PreContent
e PostContent
. Questo significa che potete manipolare questo più avanti, se necessario.
Select-String -Path "Web\*.txt" -Pattern "suspendedpage.cgi" -Context 1 | Select-Object -ExpandProperty Context -First 1 | Format-List
Altri esempi di ricerca attraverso i file di log sono in articoli come Making Sense of the Microsoft DNS Debug Log che dimostra l’utilizzo di Select-String
per guardare attraverso un log di debug DNS. Il PowerShell grep è forte in quel post.
Conclusione
Grep è uno strumento incredibilmente utile nel mondo Linux, e Select-String
offre molte delle stesse funzionalità nel mondo PowerShell. Aggiungere la natura orientata agli oggetti di PowerShell serve solo a migliorare l’utilità e l’utilità che la cmdlet offre.
Per molti amministratori di sistema, essere in grado di cercare in modo rapido ed efficiente i file di log su vari tipi, insieme alla comprensione del contesto, è una capacità incredibilmente importante e necessaria. PowerShell Select-String
rende questo facile da fare e risparmia innumerevoli ore di risoluzione dei problemi!