2010-07-20 4 views
2

Je suis nouveau à la RegEx et je veux être en mesure de rechercher et de remplacer des textes particuliers dans mon fichier texte. J'ai été capable de faire la plupart des recherches, mais en voici une que je n'arrivais pas à comprendre. Je pense que je devrais utiliser le look/regarder en avant/regarder derrière. Mais l'outil que j'utilise dit erreur de syntaxe. est essentiellement ici les données dans mon dossierextraire la première lettre d'une chaîne avec Regex

[2010-01-15 06: 18: 10,203] [0x00001388] [SHDNT] Arrêt Count Down = 2/5

[2010-01-15 06: 18: 11.203] [0x00001388] [SHDNT] Shutdown Count Down = 3/5

Et je veux être capable de capturer dans ma recherche les '[' et ']' autour de la date. J'ai pensé trouver le '[' en utilisant certains critères comme ('[' suivi de [0-9] [0-9] signifiant deux chiffres) et le ']' avec (']' en cours '. [0-9] [0-9] [0-9] 'signifiant point et 3digits).

J'ai essayé ceci mais cela donne l'erreur \ [(? = [0-9] [0-9]) pour la première recherche. Est-ce que ne me permet pas de mettre? juste après la parenthèse.

Comment dois-je effectuer la recherche?

Merci à l'avance

ÉDITÉE AJOUTER

Pour être clair, je ne suis pas avec l'aide RegEx tout langage de programmation. J'utilise un éditeur de texte qui a la fonction de recherche et de remplacement qui permet la recherche de motif. Donc, je veux supprimer les crochets autour de la date. Mais ne change rien d'autre dans mon dossier.

+1

avec quelle langue travaillez-vous? Il peut y avoir d'autres solutions n'utilisant pas RegEx. –

+0

@ p.campbell Je l'utilise avec un éditeur de texte normal avec les fonctions de recherche et de remplacement qui prennent en charge la recherche de motif. Pas un langage de programmation. – Precious

+1

D'accord, quel * éditeur utilisez-vous? Quoi qu'il en soit, vous devriez juste faire correspondre le tout, capturer la date, et le rebrancher comme @sarnold l'a fait. –

Répondre

2

L'expression régulière suivante:

^\[([^\]]+)\] 

capturera la date au début de la chaîne plus crochets, et mettra les choses entre les crochets dans un groupe qui peut être extrait par lui-même.

Notez que votre éditeur de texte peut avoir une syntaxe légèrement différente. Voici comment cela se décompose:

^ = beginning of line/string 
\[, \] = literal [ and ] characters 
() = signifies a group to capture 
[^\]] = matches any character _except_ a close bracket 
     (this keeps the match from being too greedy) 
+ = one or more of the previous 

EDIT: Cela suppose votre installation regex prend en charge les groupes (dont la plupart font). La façon la plus simple d'expliquer les groupes est simplement de vous montrer comment ils fonctionnent avec un tel moteur.Dans l'interpréteur Python:

>>> import re 
>>> s = '[2010-01-15 06:18:10.203] [0x00001388] [SHDNT] ...' 
>>> r = re.compile(r'^\[([^\]]+)\]') 
>>> m = r.search(s) 

Cela crée un objet d'expression régulière et recherche la chaîne pour la première série de texte qui lui correspond. Le résultat est renvoyé dans un objet de match:

>>> m 
<_sre.SRE_Match object at 0x1004d9558> 

Pour obtenir l'ensemble du texte qui a été adapté, la convention de Python est d'invoquer group() sur l'objet de match:

>>> m.group() 
'[2010-01-15 06:18:10.203]' 

et obtenir juste les choses entre parenthèses, je passe le numéro du groupe que je veux (dans ce cas, il n'y a qu'un seul ensemble de parens, donc un seul groupe):

>>> m.group(1) 
'2010-01-15 06:18:10.203' 

Si j'effectue un remplacement au lieu d'une recherche, j'utilise la fonction sub. Sous prend la chaîne que je veux remplacer le plein match de par, suivi de la chaîne d'entrée, et retourne la chaîne avec le remplacement effectué si une correspondance a été trouvée:

>>> r.sub('spam spam spam', s) 
'spam spam spam [0x00001388] [SHDNT] ...' 

Cependant, la chaîne de remplacement prend en charge les séquences d'échappement cela fait référence à des valeurs spécifiques de groupes capturés par le match. Une substitution de groupe est indiquée par \N, où N est le numéro du groupe. Par conséquent:

>>> r.sub(r' \1 ', s) 
' 2010-01-15 06:18:10.203 [0x00001388] [SHDNT] ...' 

qui est ce que vous voulez.

+0

Très bien. il capture la date entière. Alors, comment puis-je inclure le [et] dans le résultat tout en faisant les critères de date seulement. Dans cet exemple, q (? = u) suppose de nous donner 'q' comme résultat tout en s'assurant qu'il est suivi de 'u' sans ajouter 'u' au résultat. Comment puis-je obtenir cela parce que je veux seulement remplacer [et] avec un espace vide à la fin. – Precious

+1

Eh bien, cela va correspondre à tout, y compris les crochets, mais extrayez la partie entre parenthèses dans un groupe que vous pouvez coller dans la chaîne de remplacement. Donc, en supposant que le moteur regex de votre éditeur de texte gère les remplacements comme ceci, vous pouvez écrire en remplacement quelque chose comme '\ 1' (avec des espaces de chaque côté de \ 1) pour remplacer toute la correspondance (entre parenthèses) groupe 1 et un espace de chaque côté. –

+0

Merci beaucoup pour votre temps. J'aime l'idée c'est exactement ce que je suis en train d'accomplir mais pouvez-vous m'expliquer comment je fais cela "extraire la partie entre parenthèses dans un groupe que vous pouvez coller dans la chaîne de remplacement" ??? – Precious

1

Je ne suis pas sûr que vous devez utiliser le ou préanalyse assertions dans votre lookbehind regexp:

[email protected]:/tmp$ cat date.pl 
#!/usr/bin/perl -w 

while(<>) { 
    /^(\[\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d\])/; 
    print "$1\n"; 
} 
[email protected]:/tmp$ cat data 
[2010-01-15 06:18:10.203] [0x00001388] [SHDNT] Shutdown Count Down = 2/5 
[2010-01-15 06:18:11.203] [0x00001388] [SHDNT] Shutdown Count Down = 3/5 
[email protected]:/tmp$ ./date.pl data 
[2010-01-15 06:18:10.203] 
[2010-01-15 06:18:11.203] 

Je ne pouvais pas dire de votre description si vous faites veulent que le [ et ] autour de votre date , ou si vous ne les voulez pas. Si vous ne voulez pas les crochets, les déplacer en dehors des parens:

 /^\[(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d)\]/; 

[email protected]:/tmp$ ./date.pl data 
2010-01-15 06:18:10.203 
2010-01-15 06:18:11.203 

Notez que j'ai aussi ancré au regexp début de la ligne, au cas où la sortie comprend une chose date-heure en crochet ailleurs. En outre, j'ai sur-spécifié la date-heure par rapport à votre exemple. Considérez cela comme une paranoïa. Si vous voulez remplacer \d\d\d\d par \d{4} vous pouvez, mais dans cet exemple, je trouve la forme plus longue plus lisible.

+0

Merci, mais tout ce que je tente de faire est de supprimer les parenthèses autour de la date pour plusieurs fichiers à la fois. Alors que le reste des données est toujours le même. Je ne veux pas faire de codage. Seulement une ligne simple regex. – Precious

2

Restez simple. Il n'y a pas besoin d'utiliser une expression régulière. Si la partie date/heure correspond à ce que vous voulez, utilisez les champs et les délimiteurs de champs. voici une expression awk. Imprimez simplement la première colonne (en fermant le crochet comme délimiteurs de champs.)

$ cat file 
[2010-01-15 06:18:10.203] [0x00001388] [SHDNT] Shutdown Count Down = 2/5 
[2010-01-15 06:18:11.203] [0x00001388] [SHDNT] Shutdown Count Down = 3/5 

$ awk -F"]" '{print $1"]"}' file 
[2010-01-15 06:18:10.203] 
[2010-01-15 06:18:11.203] 

ou tout simplement imprimer des champs 1 et 2 en utilisant les espaces comme délimiteurs

$ awk '{print $1,$2}' file 
[2010-01-15 06:18:10.203] 
[2010-01-15 06:18:11.203] 

Mise à jour: Pour supprimer les crochets, utilisez simplement gsub() ou sub() sur les champs 1 et 2

$ awk '{gsub(/^\[/,"",$1);gsub(/\]$/,"",$2)}1' file 
2010-01-15 06:18:10.203 [0x00001388] [SHDNT] Shutdown Count Down = 2/5 
2010-01-15 06:18:11.203 [0x00001388] [SHDNT] Shutdown Count Down = 3/5 
0

Je suis d'accord avec ghostdog que vous devriez le garder simple, mais vous pouvez le garder simple avec des expressions régulières aussi:

  1. ^ correspond au début d'une ligne.
  2. . correspond à un seul caractère.
  3. *? correspond à la chose précédente zéro ou plusieurs fois NON-VRAIMENT, ce qui signifie qu'il n'en faut pas plus pour que le reste de la regex corresponde.

Mettre cela ensemble et vous obtenez ^.*?\] qui correspond depuis le début de la ligne à la première ] qu'il voit.

EDIT: Vous venez de voir votre réponse à ghostdog, qui a clarifié le problème. Il est toujours plus facile de faire correspondre la date entière avec les accolades. Une fois que vous avez cela, il suffit de remplacer la chaîne entière par elle-même, moins le premier et le dernier caractère. Je ne sais pas quelle langue que vous utilisez, mais en Python ce serait quelque chose comme ceci:

new_string = re.sub(r'^.*?\]',original_string,lambda m:m.group()[1:-1]) 
+0

Merci. Mais cette recherche mettra en évidence l'ensemble du match de recherche. Voici ce que j'ai fait qui m'a permis de mettre en évidence le [en début de date mais il ajoute le chiffre à cela.^\\ [(.? [0-9]) Ce que je veux faire est mettre en surbrillance seulement le '[' tout en faisant les critères de chiffre seulement mais n'a pas besoin d'être inclus dans le résultat. Est-ce que j'ai un sens? parce que regarder autour de q (? = u) imprime 'q' (suivi de 'u') il omet 'u' du résultat. – Precious

+0

C'est bien, mais je n'utilise vraiment aucun langage de programmation juste un simple éditeur de texte avec une fonction de recherche et de remplacement. – Precious

0

Parce que votre format d'entrée est si rigide prendre la façon très simple:

$ cut -c 2-24 <<EOF 
[2010-01-15 06:18:10.203] [0x00001388] [SHDNT] Shutdown Count Down = 2/5 
[2010-01-15 06:18:11.203] [0x00001388] [SHDNT] Shutdown Count Down = 3/5 
EOF 

2010-01-15 06:18:10.203 
2010-01-15 06:18:11.203 
0

Non entièrement sûr que vous avez besoin d'une expression régulière ici. S'il s'agit de trouver le premier caractère, ou de déterminer le texte entre crochets. J'ai peut-être mal compris votre question?

C# exemple:

LINQ:

string[] firsts = myFile.ReadAllLines().Select(f=>f[0]); 

Looping avec foreach:

string[] allLines = myFile.ReadAllLines(); 
foreach (string line in allLines) 
{ 
    char firstChar= line[0]; 
    Console.WriteLine("First char: " + firstChar.ToString()); 

    if (firstChar = '[') 
    { 
     int closing = line.IndexOf(']'); 
     string textWithin = line.SubString(0, closingSquare-1); 
     Console.WriteLine("Found this text within the square brackets: " + textWithin); 
    } 
} 
0

Ah, merci pour votre commentaire supplémentaire dans l'une des réponses.

Dans vim, je serais probablement utiliser l'outil de sélection visuelle: placez le curseur sur le premier [, le type ^V, G (pour arriver à la fin du fichier), puis x supprimer la colonne. Ensuite, répétez avec le premier ] caractère, ^V, G (mais G va mettre le curseur sur le caractère erroné - donc utiliser l ou la flèche droite-clé pour passer à la ]) puis tapez x pour supprimer la colonne.

Si elle n'a pas aligné parfaitement dans les colonnes (peut-être le .203 pourrait être moins de caractères, dire .2) alors je ferais ceci:

:%s/^\[// 
:%s/\(\d\)] /\1/

Notant bien sûr que la seconde regex est beaucoup plus fragile ; il va supprimer le premier ] qui se trouve entre un chiffre et un espace sur chaque ligne. Non-vim ne sera pas si ennuyeux d'échapper ( et ).

Bien sûr, si vous n'utilisez pas de vi-clone, j'espère que cela se traduira assez bien. :)

+0

Merci, mais je n'utilise pas Vim. – Precious

Questions connexes