Problèmes d'expressions régulières PowerShell

Oct 16 2020

C'est mon premier message, j'ai tendance à être en mesure de trouver ce dont j'ai besoin en lisant et en recherchant d'autres messages, mais celui-ci m'a vaincu. J'essaie d'utiliser une expression régulière dans Powershell pour rechercher des données dans un fichier texte.

Exemple de fichier texte: (Il y a des espaces dans l'exemple de fichier texte jusqu'à la fin de cette ligne)

 Impression            CONCLUSION:                                                                     
 Impression                        
            
 Impression            CONCLUSION:                                                                     
 Impression            SomeData

 Impression            CONCLUSION:                                                                     
 Impression            SomeOtherData

 Impression            CONCLUSION:                                                                     
 Impression                                         

Je cherche à trouver où la deuxième ligne est vide après la ligne avec conclusion.

C'était la base de ma simple tentative:

Get-Content -Path "C:\temp\Log\Conclusion.txt" | Select-String -Pattern "CONCLUSION:\s*\r\n\s*Impression\s*\r\n\s*Impression" -Context 1, 1

J'ai trouvé que tout ce qui a \ r \ n ne renvoie aucun résultat. J'ai essayé à la fois \ r et \ n par eux-mêmes, j'ai essayé d'obtenir le contenu sous forme brute, mais cela ne fait que renvoyer le fichier entier. L'aide est appréciée, merci.

Mise à jour: Merci pour les réponses de tout le monde, j'aurais dû préciser que j'essayais de trouver des lignes après la conclusion qui étaient vides. J'ai fini par obtenir un décompte pour commencer avec l'utilisation de Get-Content -Raw. Mes exemples de données ont légèrement changé pour ajouter une autre ligne vide avec le mot impression: Nom / Lieu Impression CONCLUSION:
Impression Impression

Ce code a pu me faire un décompte: (extrait / modifié d'un autre message du forum, je ne prends pas le crédit pour avoir proposé cela)

$ search_string = "\ s CONCLUSION: \ s \ r \ n \ s Impression \ s \ r \ n \ s Impression \ s \ r \ n \ s Impression \ s \ r \ n" $ chemin_fichier = "C: \ temp \ Log \ Conclusion.txt "$string = (Get-Content -raw -Path $file_path | Select-String$search_string -AllMatches | % { $_.matches}). count

Je travaille toujours sur un moyen d'imprimer davantage de données qui ne fonctionneraient que si vous n'utilisiez pas Raw, j'avais prévu d'utiliser le contexte pour saisir la ligne ci-dessus, mais puisque raw rassemble tout sur une seule ligne, cela ne fonctionne pas. Merci encore pour l'aide, si quelqu'un a d'autres conseils sur la possibilité d'utiliser \ r \ n et de ne pas utiliser Raw, merci de me le faire savoir.

Réponses

paddywan Oct 16 2020 at 20:50

Je ne sais pas si cela fonctionnera avec PowerShell, mais essayez-le: (*CRLF)CONCLUSION:\sImpression\s\s

https://regex101.com/r/d6Pm2k/1

Brian Oct 16 2020 at 21:46

Voici mon horrible attaque par force brute:

$blankRows = @() $targetRows = @()
$rowNum = 0 $foundRows = @()

$myFile = Get-Content $thisFile

Foreach($thisRow in $myFile){
    $rowNum++ if($thisRow -eq "Impression"){$blankRows += $rowNum}
    if ($thisRow -match 'CONCLUSION'){$targetRows += $rowNum} } Foreach($blrw in $blankRows){ if ($targetRows -contains ($blrw-1)){$foundRows += $blrw} } $foundRows
postanote Oct 17 2020 at 23:16

Pourquoi ne pas faire ça?

# Create some sample data file
@'
Impression CONCLUSION:
Impression

Impression CONCLUSION:
Impression SomeData

Impression CONCLUSION:
Impression SomeOtherData

Impression CONCLUSION:
Impression
'@ | 
Out-File -FilePath 'D:\Temp\Imprestion.txt' -Force
Get-Content -Path 'D:\Temp\Imprestion.txt'
# Results
<#
Impression CONCLUSION:
Impression

Impression CONCLUSION:
Impression SomeData

Impression CONCLUSION:
Impression SomeOtherData

Impression CONCLUSION:
Impression
#>

# Import the sample data file as a CSV, use the space as a Delimiter
Import-Csv -Path 'D:\Temp\Imprestion.txt' -Delimiter ' ' -Header Property, Value
# Results
<#
Property   Value        
--------   -----        
Impression CONCLUSION:  
Impression              
Impression CONCLUSION:  
Impression SomeData     
Impression CONCLUSION:  
Impression SomeOtherData
Impression CONCLUSION:  
Impression              
#>

# Filter by the Value property
Import-Csv -Path 'D:\Temp\Imprestion.txt' -Delimiter ' ' -Header Property, Value | 
Where-Object -Property Value -EQ $null # Results <# Property Value -------- ----- Impression Impression #> # Using Select-String and a RegEx 'Not Match' Select-String -Path 'D:\Temp\Imprestion.txt' -Pattern '^((?!Impression [a-zA-Z]).)*$'
# Results
<#
D:\Temp\Imprestion.txt:2:Impression
D:\Temp\Imprestion.txt:3:
D:\Temp\Imprestion.txt:6:
D:\Temp\Imprestion.txt:9:
D:\Temp\Imprestion.txt:11:Impression
#>

# Using Select-String and RegEx match
Select-String -Path 'D:\Temp\Imprestion.txt' -Pattern '^Impression\s*$'
# Results
<#
D:\Temp\Imprestion.txt:2:Impression
D:\Temp\Imprestion.txt:11:Impression
#>

Explication:

  • ^ est le début de l'ancre de chaîne.
  • $ est la fin de l'ancre de chaîne.
  • \ s est la classe de caractères d'espacement.
  • est une répétition zéro ou plus de.
KeithMiller Oct 17 2020 at 04:25

Je ne sais toujours pas exactement ce que vous voulez capturer, les lignes complètement vides ou celles avec Impressionet sans données suivantes.

Mais d'après la documentation, Get-Contnet :

  • Pour les fichiers, le contenu est lu une ligne à la fois et renvoie une collection d'objets, chacun représentant une ligne de contenu.

Ainsi, les <newline>caractères sont "consommés" comme séparateurs d'éléments d'un tableau de chaînes.
Essayer:

Get-Content -Path "C:\temp\Log\Conclusion.txt" | gm
(Get-Content -Path "C:\temp\Log\Conclusion.txt").Count

donc vous ne correspondrez jamais à un <newline>avec le code tel qu'il est écrit.

Vous pouvez utiliser le -Rawparamètre pour traiter le fichier comme une longue chaîne de <newline>caractères ou réécrire votre logique de recherche dans un tableau.


De plus, la documentation de Select-string montre qu'il peut prendre un fichier directement et le traiter ligne par ligne, sans avoir besoin de Get-Content.


Mettre à jour

Je ne sais toujours pas quelle ligne vous voulez sortir, mais voici un exemple de squelette de ce que je pense que vous demandez. Mes hypothèses sont:

  • Les lignes que vous recherchez sont celles sans texte après "Impression" (veuillez préciser s'il s'agit de littéraux ou de données)
  • Lorsqu'une correspondance est trouvée, la ligne précédente est capturée pour le fichier de sortie.
$File = Get-Content -Path "C:\temp\Log\Conclusion.txt" $OutLines   = @()
$EmptyMatch = '^Impression\s*$'
$i = 0 ForEach ( $line in $File ) { If ( $line -match $EmptyMatch ) { $OutLines += $File[ $i - 1 ]
    }
    $i++ } $OutLines | Set-Content 'c:\MyStuff\OutFile.txt'
Add