3
votes

Sélectionnez les noms d'hôte dans les fichiers journaux

J'ai une application qui génère des centaines de fichiers journaux texte qui ressemblent à

GC  C:\log_5.txt |
    Select-String -Pattern 'Host=\"([^\"]*)\"'

Je dois sélectionner l'hôte parmi ceux-ci J'ai essayé

DaemonReruns=2|

Phase=|

Log=false|
DS=LOG_4|
Schema=LOLYY|
DBMS=mssql|
Host=abc.XYz.com|
IDs=xxxxx,xxxx

Ne donne aucun résultat, aucune aide?


0 commentaires

6 Réponses :


2
votes
((Get-Content -Path .\log_5.txt) -match 'Host=') -replace 'Host=',''
returns all the lines starting with Host=

1 commentaires

cool , il vient avec Host = abc.domain.com | pouvons-nous exclure Host = et | juste besoin de l'url



3
votes

Il n'y a pas de guillemets dans votre exemple d'entrée. Essayez cette expression régulière:

get-content C:\log_5.txt | foreach {
    if ($_ -match 'Host=([^|]+)') {
        $Matches.1
    }
}

Remarque: Cela renvoie en fait les noms d'hôte, pas seulement la ligne.


4 commentaires

Cool, cela fonctionne mais pas capable de trier les fichiers uniques `gci C: \ logs | où {$ _. Extension -comme '* .txt' -ou $ _. Extension -comme '* .proc'} | Foreach {Get-Content $ _. FullName} | foreach {if ($ _ -match 'Host = ([^ |] +)') {$ data = $ Matches.1 $ data | Sort-Object -Unique}} `


@Jondrew Placez le tri à la toute fin du pipeline: ... {$ Matches.1}} | sort -Unique


il ne sera pas foreach {if ($ _ -match 'Host = ([^ |] +)') {$ Matches.1 | sort -Unique}}


@Jondrew foreach {if ($ _ -match 'Host = ([^ |] +)') {$ Matches.1}} | sort -Unique



3
votes

la réponse utile de marsze résout le problème avec votre regex et utilise un ForEach-Object ( foreach ) pour extraire et renvoyer des correspondances via l'opérateur -match et la variable automatique $ Matches .

Voici un résumé (et mieux -performing) à l'aide du commutateur instruction :

PS> switch -Regex -File C:\log_5.txt { 'Host=([^|]+)' { $Matches[1] } }
abc.XYz.com

Notez que -File n'accepte pas les chemins basés sur des caractères génériques, cependant, dans l'ordre pour traiter plusieurs fichiers, vous devrez les parcourir via Get-ChildItem ou Convert-Path.


0 commentaires

2
votes

Juste pour le plaisir ... la solution ultra-rapide :

$regex = [Regex]::new('Host=([^|]+)', 'Compiled, IgnoreCase, CultureInvariant')
& {foreach ($line in [IO.File]::ReadLines("C:\log_5.txt")) {
    $m = $regex.Match($line)
    if ($m.Success) {
        $m.Groups[1].Value
    }
}}

p >


3 commentaires

Btw, il semble que ce qui ralentit switch -Regex par rapport à [regex] .Match () est l'effort supplémentaire de traduire les informations de correspondance dans les $ Matches hashtable.


@ mklement0 Ouais PS est toujours un langage de script conçu pour être facilement utilisable, pas rapide. Si j'écris la même chose en code C #, compilez-le avec Add-Type et appelez cela, c'est quelques dizaines de fois plus rapide.


Belle solution C #; autre brève tangente: voici un piège amusant avec switch -File : github. com / PowerShell / PowerShell / issues / 8988



2
votes

Si vos logs sont énormes, cela pourrait valoir la surcharge de Add-Type , et le reste serait beaucoup plus rapide:

Add-Type '
using System.IO;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace PowerShell
{
    public class Tools
    {
        static Regex regex = new Regex(@"Host=([^|]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
        public static IEnumerable<string> GetHosts(string path)
        {
            foreach(var line in File.ReadLines(path))
            {
                var matches = regex.Match(line);
                if (matches.Success)
                {
                    yield return matches.Groups[1].Value;
                }
            }
        }
    }
}'

# call this for each log file (very fast)
[PowerShell.Tools]::GetHosts("C:\log_5.txt")


0 commentaires

1
votes

Les autres réponses traitent assez bien du côté des expressions régulières. Chaque fois que je vois de petits journaux comme celui-ci, je pense toujours à ConvertFrom-StringData qui

convertit une chaîne contenant une ou plusieurs paires clé / valeur en une table de hachage.

De: help ConvertFrom-StringData

Dans sa forme de base, nous faisons juste quelque chose comme ceci:

[pscustomobject](Get-Content -File $pathToFile | ForEach-Object{$_.trimend("|")} | Out-string | ConvertFrom-StringData)

[pscustomobject]((Get-Content -Raw -File $pathToFile) -replace "(?m)\|$" | ConvertFrom-StringData)

Ce qui vous donnerait un objet PowerShell avec lequel vous pouvez interagir facilement! p >

DS           : LOG_4|
Schema       : LOLYY|
IDs          : xxxxx,xxxx
Log          : false|
DBMS         : mssql|
Host         : abc.XYz.com|
Phase        : |
DaemonReruns : 2|

Vous doutez que vous ayez besoin des tuyaux de fin. Vous pouvez les supprimer avec des méthodes d'expression régulière ou de chaîne plus simples.

$pairs = Get-Content -Raw -File $pathtofile | ConvertFrom-StringData
[pscustomobject]$pairs

Dans tous les cas, cela vous donne plus d'options sur la façon dont vous devez traiter vos données.


0 commentaires