web-dev-qa-db-fra.com

Comment "déboguer" une expression régulière avec sed?

J'essaie d'utiliser une expression rationnelle en utilisant sed. J'ai testé mon regex avec kiki, une application gnome pour tester regexpd, et cela fonctionne dans kiki.

date: 2010-10-29 14:46:33 -0200;  author: 00000000000;  state: Exp;  lines: +5 -2;  commitid: bvEcb00aPyqal6Uu;

Je veux remplacer author: 00000000000; avec rien. J'ai donc créé l'expression régulière, qui fonctionne lorsque je la teste dans kiki:

author:\s[0-9]{11};

Mais ne fonctionne pas lorsque je le teste dans sed.

sed -i "s/author:\s[0-9]{11};//g" /tmp/test_regex.txt

Je sais que regex a différentes implémentations, et cela pourrait être le problème. Ma question est: comment puis-je au moins essayer de "déboguer" ce qui se passe avec sed? Pourquoi ça ne marche pas?

Ma version de sed n'aime pas le {11} bit. Traitement de la ligne avec:

sed 's/author: [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9];//g'

fonctionne bien.

Et la façon dont je le débogue est exactement ce que j'ai fait ici. Je viens de construire une commande:

echo 'X author: 00000000000; X' | sed ...

et supprimé les choses regex les plus avancées une à la fois:

  • utilisé <space> au lieu de \s, ne l'a pas corrigé.
  • remplacé [0-9]{11} avec 11 exemplaires de [0-9], ça a marché.

C'est à peu près had pour être l'un de ceux-là puisque j'ai déjà utilisé toutes les autres fonctionnalités de votre expression régulière avec sed avec succès.

Mais, en fait, cette volonté fonctionne réellement sans les affreuses copies de [0-9], il suffit d'échapper aux accolades [0-9]\{11\}. Je dois admettre que je n'ai pas réussi à essayer cela car cela fonctionnait bien avec les multiples et je ne me préoccupe généralement pas trop de brièveté dans sed car j'ai tendance à l'utiliser davantage pour quick'n 'sales boulots :-)

Mais la méthode d'accolade est beaucoup plus concise et adaptable et il est bon de savoir comment le faire.

21
paxdiablo

Dans sed, vous devez échapper aux accolades. "s/author:\s[0-9]\{11\};//g" devrait marcher.

Sed n'a pas de capacité de débogage. Pour vous tester, simplifiez la ligne de commande de manière itérative jusqu'à ce que vous obteniez quelque chose à travailler, puis reconstruisez.

entrée de ligne de commande:

$ echo 'xx a: 00123 b: 5432' | sed -e 's/a:\s[0-9]\{5\}//'

sortie en ligne de commande:

xx  b: 5432
21
verisimilidude

Il y a un script Python appelé sedsed par Aurelio Jargas qui montrera l'exécution pas à pas d'un script sed. Un débogueur comme celui-ci ne va pas aider dans le cas de caractères pris à la lettre (par exemple {) par rapport à une signification particulière (par exemple \{), en particulier pour une substitution simple, mais cela aidera quand un script plus complexe sera débogué.

La dernière version SVN .
La version stable la plus récente .
Avertissement: je suis un contributeur mineur à sedsed.

sedsed example

Un autre débogueur sed, sd par Brian Hiles, écrit comme un script Bourne Shell (je n'ai pas utilisé celui-ci).

17
Dennis Williamson

Vous devez utiliser l'indicateur -r pour l'expression régulière étendue:

sed -r 's/author:\s[0-9]{11};//g'

ou vous devez échapper aux {} caractères:

sed 's/author:\s[0-9]\{11\};//g'
12
Ray

Cela ressemble plus à une expression régulière de Perl qu'à une expression régulière de sed. Peut-être préféreriez-vous utiliser

Perl -pi.orig -e 's/author:\s[0-9]{11};//g' file1 file2 file3

Au moins de cette façon, vous pouvez toujours ajouter -Mre=debug pour déboguer l'expression régulière.

2
tchrist

Vous utilisez le drapeau -i de manière incorrecte. Vous devez mettre lui donner une chaîne à mettre sur le fichier temporaire. Vous devez également échapper à vos accolades.

sed -ibak -e "s/author:\s[0-9]\{11\};//g" /tmp/test_regex.txt

Je débogue habituellement ma déclaration en commençant par une expression régulière que je sais fonctionnera (comme 's/author // g' dans ce cas). Lorsque cela fonctionne, je sais que j'ai les bons arguments. Ensuite, j'élargis progressivement l'expression régulière.

2
Brian Clements

Si vous souhaitez déboguer une commande sed, vous pouvez utiliser la commande w (écriture) pour vider quelles lignes sed correspond à un fichier.

De sed manpages:

Commandes acceptant les plages d'adresses

(...)

w nom de fichier

Écrivez l'espace de motif actuel dans le nom de fichier.


Appliquer à votre question

Utilisons un fichier nommé sed_dump.txt comme fichier de vidage sed.

1) Générez le vidage sed:

sed "/author:\s[0-9]{11};/w sed_dump.txt" /tmp/test_regex.txt

2) Vérifiez le fichier sed_dump.txt contenu:

cat sed_dump.txt

Sortie:

Il est vide ...

3) Essayer d'échapper au caractère de contrôle de l'expression rationnelle '{':

sed "/author:\s[0-9]\{11\};/w sed_dump.txt" /tmp/test_regex.txt

4) Vérifiez le fichier sed_dump.txt contenu:

cat sed_dump.txt

Sortie:

date: 2010-10-29 14:46:33 -0200; auteur: 00000000000; état: Exp; lignes: +5 -2; commitid: bvEcb00aPyqal6Uu;

Conclusion

À l'étape 4), une ligne a été mise en correspondance, cela signifie que sed correspond à votre modèle dans cette ligne. Cela ne garantit pas la bonne réponse, mais c'est un moyen de déboguer en utilisant sed lui-même.

1
gagallo7

Le fait que vous remplacez author: 00000000000 est déjà dit dans sed lorsque vous ajoutez le s avant le premier /.

0
Alberto Zaccagni