GREP nombre impair

eZula Messages postés 3509 Statut Contributeur -  
eZula Messages postés 3509 Statut Contributeur -
Salut,

Pour déboguer un batch DOS, je cherche à matcher des lignes foireuses, par exemple celles qui pourraient contenir un guillemet suivi de n'importe quelle expression sauf un guillemet. Aucun de mes essais n'a abouti à qque chose de valable.
Finalement, encore plus intéressant, j'ai pensé plutôt à matcher ttes les lignes d'un fichier qui contiennent un nombre impair de guillemets

"coucou"
cou"cou
cou""cou
coucou"
"couco"u"


donc ici lignes 2, 4 et 5. Y a-t-il, avec l'option -c par exemple une solution à ce problème sans passer par aucune autre commande Linux (en dehors de SED à la rigueur) ?
Ce serait bien aussi de caser l'option -n pour avoir l'affichage des lignes et de leurs numéros

Je suis également intéressé par une regexp correspondant au premier essai (simple curiosité)

Merci

43 réponses

dubcek Messages postés 19032 Date d'inscription   Statut Contributeur Dernière intervention   5 641
 
Windoz n'aime pas les ', il faut donc des " et avec tous ceux à l'intérieur c'est galère, je te conseille de le mettre dans un fichier

$ type f1.awk
/\"/ {x=$0;n=gsub("\"", "X", x);if(n % 2 ) print NR, $0 }

et d'exécuter awk -f f1.awk
0
eZula Messages postés 3509 Statut Contributeur 392
 
ha, très bien :

2 cou"cou
4 coucou"
5 "couco"u"


Est-ce que tu pourrais expliciter cette commande stp ? je méconnais awk mais pourtant j'ai l'impression qu'il pourrait me rendre bien des services par la suite.

=======

Donc, je reviens sur le problème qui suivait, avec ces fameux %. Il faudrait rechercher les lignes contenant un nbre impair de &. J'ai essayé d'adapter ta commande :

/&/ {x=$0;n=gsub("%", "X", x);if(n % 2 ) print NR, $0 } 


mais ça ne prend pas, ni en protégeant le \& (warning: escape sequence `\%' treated as plain `%')
0
eZula Messages postés 3509 Statut Contributeur 392
 
Mince, j'ai rien dit :

/\&/ {x=$0;n=gsub("&", "X", x);if(n % 2 ) print NR, $0 } 


marche très bien, merci pour cette piste fort intéressante. J'ai du m'embrouiller en prenant un antislash pour une protection dans ta commande précédente.

Je vais essayer de comprendre comment ça fonctionne
0
dubcek Messages postés 19032 Date d'inscription   Statut Contributeur Dernière intervention   5 641
 
en détail
/\"/ {x=$0;n=gsub("\"", "X", x);if(n % 2 ) print NR, $0 }
/\"/     on ne traite que les lignes qui contiennent ", protégé parce que c'est un séparateur
x=$0     on sauve la ligne ($0) dans une variable x
n=gsub("\"", "X", x)     on substitue chaque " par le caractère X dans la variable x, gsub retournant dans n le nombre de substitutions,  donc le nomnbre de "
if(n % 2 )      si le nombre de " modulo 2 est non-nul, le nombre est impair
print NR, $0     on imprime le No de la ligne (NR est une variable interne de awk) et la ligne entière $0
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
eZula Messages postés 3509 Statut Contributeur 392
 
echo cmire | awk 'BEGIN {FS="c"} {print $2$5$4$1$3}'


je m'entraine :)

Tiens, juste un dernier truc, et par rapport à cette dernière commande (censée afficher "merci"). Est-il possible de définir le séparateur "caractère alphabétique" par exemple pour ordonner une expression toute simple ? j'ai essayé [a-z] mais il n'en veut pas, j'ai donc du partir sur la première lettre de l'expression.

Promis c'est la dernière question ;)
0
dubcek Messages postés 19032 Date d'inscription   Statut Contributeur Dernière intervention   5 641
 
le séparateur peut-être n'importe quelle expression régulière ou un/des mots. Dans ton exemple, il faut spécifier qu'il n'y a pas de séparateur ou plutôt que le séparateur est "rien"

$ echo cmire | awk 'BEGIN {FS=""} {print $2$5$4$1$3}'
merci
0
eZula Messages postés 3509 Statut Contributeur 392
 
OK ça roule. Je précise juste que sous windows (bien obligé de faire avec :( ) - et en tout cas avec awk.exe et gawk.exe - ça fonctionne sous condition de protéger les guillemets du séparateur

echo cmire | awk "BEGIN {FS=\"\"} {print $2$5$4$1$3}"


sinon c'est

awk: BEGIN {FS="}
awk:           ^ unterminated string
Le processus a tenté d'écrire sur un canal inexistant.


Merci encore et à ++
0
eZula Messages postés 3509 Statut Contributeur 392
 
Salut,

je suis tjs sur ce débogage et je rencontre un problème de logique avec cette condition :

Outil\GREP -nE "(\(|\))" %%G &&ECHO ==^> Parenthèse

sur mon fichier test j'ai deux lignes trafiquées comme suivant :

%SystemRoot%\)inform.dat
%SystemRoot%\(nvchost.exe


et voilà la délation du débogueur :

3:%SystemRoot%\)inform.dat
4:%SystemRoot%\(nvchost.exe ==> Parenthèse


vous constatez comme moi que ==> Parenthèse n'apparait que sur la ligne où se trouve le 1er motif de grep càd la parenthèse ouverte ( ; bien entendu je souhaiterais que ça apparaisse pour chaque motif.

Je suis sur que je vous embête à poser mes questions windows dans ce forum mais est-ce que ce problème incombe à grep d'après vous : sous Linux ça donnerait quoi svp ?

Merci
0
eZula Messages postés 3509 Statut Contributeur 392
 
salut,

tu as raison, je viens de réaliser qu'il n'affiche cet echo qu'une fois toutes les lignes testées,

je vais voir autrement, merci
0
dubcek Messages postés 19032 Date d'inscription   Statut Contributeur Dernière intervention   5 641
 
en ligne de commande en DOS

$ awk "/\(|\)/ {print $0, \"==^> Parenthèse\"}" f1.txt
%SystemRoot%\)inform.dat ==> ParenthÞse
%SystemRoot%\(nvchost.exe ==> ParenthÞse
0
jipicy Messages postés 41342 Statut Modérateur 4 896
 
Avec "sed" ;-))
sed -n "/\(\|\)/ s/.*/& ==> Parenthèse/p"  fichier
%SystemRoot%\)inform.dat ==> Parenthèse
%SystemRoot%\(nvchost.exe ==> Parenthèse
0
eZula Messages postés 3509 Statut Contributeur 392
 
Très bien, merci pour ces solutions :)
j'aimerais retenir awk car justement j'ai déjà le fichier f1.awk http://www.commentcamarche.net/forum/affich 11856910 grep nombre impair?page=2#25

Par contre si je mets

AWK "/\(|\)/ {print $0, \"==^> Parenthèse\"}" %%G 


dans le batch ça fonctionne, mais dans Outil\f1.awk, sous la première ligne

/\&/ {x=$0;n=gsub("&", "X", x);if(n % 2 ) print NR, $0 }
/\(|\)/ {print $0, \"==^> Parenthèse\"}


avec bien sur AWK -f Outil\f1.awk %%G pour le lancer ça ne marche pas :

awk: Outil\f1.awk:2: /\(|\)/ {print NR, $0, \"==> Parenthèse\"}
awk: Outil\f1.awk:2:                        ^ backslash not last character on line


PS : j'ai ajouté NR car je voudrais qu'il me mette le résultat de la même manière que grep :

1.ligne ==> argument


même ça ça marche pas :(

j'aimerais faire pareil avec les guillemets

/\"/ {print NR, $0, \"==> Guillemet\"}
0
dubcek Messages postés 19032 Date d'inscription   Statut Contributeur Dernière intervention   5 641
 
le problème c'est la ligne de commande DOS, qui exige des ", donc il faut protéger ceux du print avec \ et qui comprend > comme une redirection qu'il faut aussi protéger, mais avec ^ !!!

mais rien de tout ça dans un fichier de commande awk :
/\(|\)/ {print $0, "==> Parenthèse"}
0
eZula Messages postés 3509 Statut Contributeur 392
 
je comprends pas... plus aucune détection, plus rien ne marche, c'est horrible :))

awk: Outil\f1.awk:3: /\"/ {print NR, $0, ==> Guillemet" }
awk: Outil\f1.awk:3:                     ^ syntax error
awk: Outil\f1.awk:3: /\"/ {print NR, $0, ==> Guillemet" }
awk: Outil\f1.awk:3:                                  ^ unterminated string


avec ou sans espace avant le } pareil

sinon y'a la solution SED de jipicy qui est intéressante, mais c'est pour aller au bout des choses quand même
Et pour le NR, c'est étrange qu'il ne l'affiche pas, non ?
0
jipicy Messages postés 41342 Statut Modérateur 4 896
 
/\"/ {print NR, $0, ==> Guillemet" }

C'est quoi c'est anti-slash suivi d'un guillemet ???

Il n'en manque pas un non plus avant le "==> ???
0
eZula Messages postés 3509 Statut Contributeur 392
 
non, en fait c'est guillement tout court (protégé par un \), par exemple un résultat attendu serait

4.%SystemRoot%\infor"m.dat ==> Guillemet


résultat effectif sans protection :

awk: Outil\f1.awk:3: /"/ {print NR, $0, ==> Guillemet"}
awk: Outil\f1.awk:3:                    ^ syntax error
0
jipicy Messages postés 41342 Statut Modérateur 4 896
 
Oops j'avions pas vu que tu cherchais des guillemets, j'en étais resté aux parenthèses ;-((

Au cas ou tu voudrais revenir sur la commande "sed" (bien que je pense que dubcek devrait trouver aisément d'où vient le problème), je te mets la syntaxe avec le comptage de ligne :
sed '=' fichier | sed -n 'N;s/\n/ /;/\(\|\)/ s/.*/& ==> Parenthèse/p'
0
dubcek Messages postés 19032 Date d'inscription   Statut Contributeur Dernière intervention   5 641
 
le premier " est protégé parce ce n'est pas un séparateur mais un caractère recherché et il faut 2 " pour définir une chaine de caractères à afficher par la commande print
/\"/ {print NR, $0, "==> Guillemet" }

$ awk -f f1.awk < f1.txt
1 %SystemRoot%\)inf"orm.dat ==> Guillemet
0
eZula Messages postés 3509 Statut Contributeur 392
 
Ok ça semble marcher, merci ;)
J'ai ajouté ceci

/\"/ {print NR":"$0, "==> Guillemet" } 


pour avoir à coté du n° de ligne un ":"

Juste une dernières question : pour la "négation" d'affichage de ligne ("tout sauf") il y aurait une autre possibilité que ça

/^%/ {if(found==0) { print NR, $0, " ==> Ne commence pas par %" ; found=1;} next; }


Je cherche les lignes qui ne commencent par par un % et ça donne un résultat à côté de la plaque (par exemple : 1 %SystemRoot%\inform.dat" ==> Ne commence pas par %)
0
jipicy Messages postés 41342 Statut Modérateur 4 896
 
Normalement la négation s'obtient avec un "!" (point d'exclamation) :
!/^%/ { print NR, $0, " ==> Ne commence pas par %" }; next; }
0
eZula Messages postés 3509 Statut Contributeur 392
 
Edition : ok comme ça

!/^\%/ {if(found==0) { print NR":"$0, " ==> Ne commence pas par %" ; found=1;} next; }


Merci :)
0