GREP nombre impair

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
Configuration: Windows XP
Firefox 3.0.8

43 réponses

Résumé de la discussion

La problématique consiste à détecter dans un fichier les lignes contenant un nombre impair de guillemets, dans le cadre du débogage d'un batch DOS, en privilégiant sed ou awk. Plusieurs réponses privilégient awk pour compter les guillemets et restituer les lignes dont le compte est impair, en utilisant gsub et une condition modulo. Des variantes existent, comme traiter les lignes contenant des guillemets et déterminer la parité via gsub, ou combiner sed et substitution pour évaluer la présence et l'absence des guillemets. En pratique, certains exemples affichent le numéro de ligne et son contenu lorsque le comptage est impair, tout en signalant que l'échappement des guillemets sur Windows peut compliquer l'analyse.

Bobot (l’IA à votre service)
  1. Contributeur
    Tiens ça pourrait être très intéressant ça aussi
    1. Contributeur
      et on peut affiner, par ex. lignes dont le champ 2 ne contient pas %
      $2 !~ /%/
      lignes dont le champ 3 n'est pas égal à %
      $3 !~ /^%$/
      1. Contributeur
        Edition : ok comme ça

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


        Merci :)
        1. Modérateur
          Normalement la négation s'obtient avec un "!" (point d'exclamation) :
          !/^%/ { print NR, $0, " ==> Ne commence pas par %" }; next; }
          1. Contributeur
            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 %)
            1. Contributeur
              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
              1. Contributeur
                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
                1. Modérateur
                  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'
              2. Modérateur
                /\"/ {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 "==> ???
                1. Contributeur
                  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 ?
                  1. Contributeur
                    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"}
                    1. Contributeur
                      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\"}
                      1. Modérateur
                        Avec "sed" ;-))
                        sed -n "/\(\|\)/ s/.*/& ==> Parenthèse/p"  fichier
                        %SystemRoot%\)inform.dat ==> Parenthèse
                        %SystemRoot%\(nvchost.exe ==> Parenthèse
                        1. Contributeur
                          en ligne de commande en DOS

                          $ awk "/\(|\)/ {print $0, \"==^> Parenthèse\"}" f1.txt
                          %SystemRoot%\)inform.dat ==> ParenthÞse
                          %SystemRoot%\(nvchost.exe ==> ParenthÞse
                          1. Contributeur
                            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
                            1. Contributeur
                              hello
                              parce que le echo ne s'exécute qu'une fois et après la dernière ligne, il faut plutôt utiliser sed ou awk
                              1. Contributeur
                                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
                                1. Contributeur
                                  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 à ++
                                  1. Contributeur
                                    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
                                    1. Contributeur
                                      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 ;)
                                      • 1
                                      • 2
                                      • 3