2
votes

Utilisation de Select-String pour faire correspondre plusieurs modèles à une seule ligne et écrire dans la sortie

J'essaye de construire un script simple pour utiliser regex et faire correspondre plusieurs modèles sur une seule ligne - de manière récursive dans un fichier d'entrée, et écrire le résultat dans un fichier de sortie. Mais je frappe un mur:

Exemple de texte:

|KDDT111D|DIH0345S|10 Physical|

Voici ce que j'ai jusqu'à présent:

XXX

Sortie:

'KDDT111D.DIH0345S' 10 Physical

Sortie souhaitée:

'KDDT111D.DIH0345S'

Pour une raison quelconque, je ne parviens pas à écrire les deux modèles dans output.txt. Idéalement, une fois que cela fonctionne, j'aimerais utiliser Export-Csv pour obtenir quelque chose d'un peu plus propre comme:

$table = [regex] "'.*'"
$discard = [regex] "\d* PHYSICAL"

Select-String -Pattern ($table, $discard) -AllMatches .\test.txt | foreach {
    $_.Matches.Value
} > output.txt


3 Réponses :


1
votes

Je pense que vous trouverez l'opérateur -match un peu plus adapté à cela. [ grin ] en utilisant des correspondances nommées avec votre échantillon stocké dans $ InStuff , ceci ...

Name                           Value                                                                              
----                           -----                                                                              
Space                          KDDT111D                                                                           
SubSpace                       DIH0345S                                                                           
Discarded                      10 PHYSICAL                                                                        
0                              BMC12345 COMBINED PHASE STATISTICS: 31 ROWS SELECTED FOR SPACE 'KDDT111D.DIH0345...

... donne l'ensemble suivant des correspondances ...

$InStuff -match ".+SPACE '(?<Space>.+)\.(?<SubSpace>.+)'.+: (?<Discarded>.+) \(.+"

les correspondances nommées peuvent être adressées par $ Matches. .


4 commentaires

Je ne pense pas que ce soit la direction dans laquelle je veux aller, mais j'apprécie l'idée. Le fichier d'entrée contiendra des centaines d'enregistrements similaires à l'exemple de texte que j'ai fourni ci-dessus. Je voudrais que le script récupère le fichier d'entrée dans un répertoire spécifié. Le script doit ensuite extraire de manière récursive les valeurs de correspondance «Espace», «Sous-espace» et «Supprimé» et écrire cette sortie pour chaque enregistrement dans un fichier txt / csv.


@Jonmonjovi - ok ... mais regex est généralement la voie à suivre pour les gros fichiers. [ grin ] Je ne parviens pas à faire fonctionner la cmdlet Select-String avec un tableau de modèles tels que ceux que vous avez répertoriés. Je soupçonne que cela ne fonctionnera pas du tout de cette façon. [ soupir ... ]


Malheureusement, je n'ai pas pu répliquer vos résultats à l'aide de l'opérateur de correspondance et de mon fichier d'entrée. Informations sur la version PS ci-dessous: PSVersion 5.1.17134.407 PSEdition Desktop PSCompatibleVersions {1.0, 2.0, 3.0, 4.0 ...} BuildVersion 10.0.17134.407 CLRVersion 4.0.30319.42000 WSManStackVersion 3.0 PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1


il y a tellement de façons dont une regex peut se tromper [ grin ] ... il est presque inutile d'en discuter sans voir à la fois le code réel que vous avez utilisé ET quelques lignes du fichier de données [nettoyé].



1
votes

Vous avez rencontré une limitation de Select-String : la propriété .Matches de la [Microsoft.PowerShell.Commands.MatchInfo] objets qui Select-String émet pour chaque objet d'entrée (ligne) ne contient que les (potentiellement multiples) correspondances pour la première expression régulière transmise au
-Pattern . [1]

Vous pouvez contourner le problème en transmettant une expression régulière unique à la place, en combinant les expressions régulières d'entrée via alternance ( | ):

fo
az

Un exemple simplifié:

# ('f.', '.z' -join '|') -> 'f.|.z'
'foo bar baz' | Select-String -AllMatches ('f.', '.z' -join '|') |
  ForEach-Object { $_.Matches.Value }


0 commentaires

0
votes

Merci aux contributeurs pour les idées et l'expérience d'apprentissage. J'ai pu obtenir le résultat souhaité en utilisant une combinaison des deux réponses reçues.

J'ai trouvé que l'opérateur -match ne renvoyait que la première occurrence de la correspondance de motif regex à partir du fichier source, donc je nécessaire pour ajouter une boucle foreach afin de renvoyer récursivement des correspondances dans tout le fichier journal.

J'ai également modifié l'expression régulière pour n'inclure que les valeurs de rejet supérieures à 0.

Exemple de texte:
KDDT000D|KDIADR0S| 11 PHYSICAL
KDDT000D|KDLADD0S| 24845 PHYSICAL

Exemple:

  $regex = ".+SPACE '(?<Space>.+)\.(?<SubSpace>.+)'.+: (?<Discarded>.+) .[1-9][0-9]*\s\b"

    $timestamp = Get-Date
    $timestamp = Get-Date $timestamp -f "MM_dd_yy"
    $dir = "C:\Users\JonMonJovi\"

    cat $dir\*.log.txt | where {
        $_ -match $regex
    } | foreach {
        $Matches.Space, $Matches.SubSpace, $Matches.Discarded -join "|"
    } > C:\Users\JonMonJovi\Discarded\Discard_Log_$timestamp.txt

BMC51472I COMBINED PHASE STATISTICS:  0 ROWS SELECTED FOR SPACE 'KDDT000D.KDAICH0S', 0 ROWS SELECTED BUT DISCARDED DUE TOBMC51479I COMBINED PHASE STATISTICS:  0 PHYSICAL (0 LOGICAL) RECORDS DISCARDED TO SYSDISC
BMC51472I COMBINED PHASE STATISTICS:  3499604 ROWS SELECTED FOR SPACE 'KDDT000D.KDAIND0S', 0 ROWS SELECTED BUT DISCARDED BMC51479I COMBINED PHASE STATISTICS:  0 PHYSICAL (0 LOGICAL) RECORDS DISCARDED TO SYSDISC
BMC51472I COMBINED PHASE STATISTICS:  1 ROWS SELECTED FOR SPACE 'KDDT000D.KDCISR0S', 0 ROWS SELECTED BUT DISCARDED DUE TOBMC51479I COMBINED PHASE STATISTICS:  0 PHYSICAL (0 LOGICAL) RECORDS DISCARDED TO SYSDISC
BMC51472I COMBINED PHASE STATISTICS:  9185775 ROWS SELECTED FOR SPACE 'KDDT000D.KDIADR0S', 0 ROWS SELECTED BUT DISCARDED BMC51479I COMBINED PHASE STATISTICS:  11 PHYSICAL (11 LOGICAL) RECORDS DISCARDED TO SYSDISC
BMC51472I COMBINED PHASE STATISTICS:  0 ROWS SELECTED FOR SPACE 'KDDT000D.KDICHT0S', 0 ROWS SELECTED BUT DISCARDED DUE TOBMC51479I COMBINED PHASE STATISTICS:  0 PHYSICAL (0 LOGICAL) RECORDS DISCARDED TO SYSDISC
BMC51472I COMBINED PHASE STATISTICS:  2387375 ROWS SELECTED FOR SPACE 'KDDT000D.KDICMS0S', 0 ROWS SELECTED BUT DISCARDED BMC51479I COMBINED PHASE STATISTICS:  0 PHYSICAL (0 LOGICAL) RECORDS DISCARDED TO SYSDISC
BMC51472I COMBINED PHASE STATISTICS:  1632821 ROWS SELECTED FOR SPACE 'KDDT000D.KDIPRV0S', 0 ROWS SELECTED BUT DISCARDED BMC51479I COMBINED PHASE STATISTICS:  0 PHYSICAL (0 LOGICAL) RECORDS DISCARDED TO SYSDISC
BMC51472I COMBINED PHASE STATISTICS:  0 ROWS SELECTED FOR SPACE 'KDDT000D.KDLADD0S', 0 ROWS SELECTED BUT DISCARDED DUE TOBMC51479I COMBINED PHASE STATISTICS:  24845 PHYSICAL (24845 LOGICAL) RECORDS DISCARDED TO SYSDISC

À partir de là, je suis capable d'utiliser le tube délimité. txt à importer dans Excel, répondant à mes exigences.


0 commentaires