2010-03-12 7 views
0

Le titre le plus convulatoire du monde que je connaisse, un exemple devrait l'expliquer mieux. J'ai un gros fichier txt dans le format ci-dessous, bien que les détails et le montant des lignes changeront chaque fois:Regex pour trouver un mot, puis extraire une ligne contenant la première occurrence d'un mot différent immédiatement avant le mot d'origine?

Username: john_joe     Owner: John Joe 
Account: 
CLI:  
Default: 
LGICMD: 
Flags: 
Primary days: 
Secondary days: 
No access restrictions 
Expiration: 
Pwdlifetime: 
Last Login: 
Maxjobs:  
Maxacctjobs: 
Maxdetach: 
Prclm:  
Prio:  
Queprio: 
CPU:  
Authorized Privileges: 
    BYPASS 
Default Privileges: 
    SYSPRV 

Cette séquence est répétée deux mille fois pour les utilisateurs différents. J'ai besoin de trouver chaque utilisateur (idéalement toute la première ligne de ce qui précède) qui a SYSPRV sous "Autorisations par défaut". Je sais que je pourrais écrire une application pour faire ceci, j'espérais juste que leur pourrait être une bonne regex que je pourrais utiliser.

Vive

+0

Le début de chaque enregistrement marqué d'une ligne "Nom d'utilisateur:"? Sinon, y a-t-il un autre moyen de distinguer les limites des enregistrements? – msw

+0

Quelle langue ou saveur regex utilisez-vous? Quelle est la taille du fichier et comment le lisez-vous? Avez-vous tout slurp en mémoire à la fois? –

Répondre

3
^Username:\s*(\S+)((?!^Username).)*Default Privileges:\s+SYSPRV 

avec la possibilité de faire^début de match en ligne, et de faire des sauts de ligne match de points, isolera les dossiers et saisir le nom d'utilisateur dans backreference pas. 1. Dites-moi quelle langue vous utilisez, et je vais fournir un exemple de code.

Explication:

^Username:\s: "Username" au début de la ligne, deux points et les espaces blancs.

(\S)+ « . Correspond à aucun des caractères non-blancs et les capturer dans backreference no 1. Ce sera le nom d'utilisateur

((?!Username).)*. Faites correspondre un caractère aussi longtemps que ce n'est pas le « U » de « Nom d'utilisateur » . Cela garantit que nous ne franchirons pas accidentellement dans l'enregistrement suivant

Default Privileges:\s+SYSPRV:.. correspondent au texte requis

Ainsi en Python, par exemple, vous utilisez:

result = re.findall(r"(?sm)^Username:\s*(\S+)((?!^Username).)*Default Privileges:\s+SYSPRV", subject) 
+0

+1 Bonne réponse. Plus robuste pour l'assertion négative serait ceci: '(?!^Nom d'utilisateur:)'. – FMc

+0

Merci pour la réponse rapide Tim. J'espérais faire ça avec grep, est-ce possible? Merci. – Hinchy

+0

Je ne suis pas sûr - je ne connais pas assez bien le jeu d'outils Unix. Je pense que le grep d'origine ne supporte pas lookahead (que cette regex utilise), et est basé sur une ligne, donc vous ne pouvez pas faire correspondre les choses sur plusieurs lignes. Mais je peux me tromper complètement à ce sujet. –

Questions connexes