Shell/Batch grep + sed

Shell/Batch grep + sed - Shell/Batch - Programmation

Marsh Posté le 11-01-2011 à 17:01:31    

Bonjour,
 
Je cherche à faire un petit script qui va permettre de récupérer un numéro de version dans un fichier cpp.
J'aimerais donc récupérer le nom du fichier et son numéro de version.
Cela fait maintenant longtemps que je n'ai plus fait ce genre de chose et de plus le sed n'a jamais été ma tasse de thé :)
 
Je suis sur Cygwin et la méthode recursive de grep ne fonctionne pas, donc voici ma command qui va me donner ces résultat.

Code :
  1. find -name *.cpp | xargs grep "sVersion(L"


 
voici la réponse:

Code :
  1. ./src/component/KTBaseForm.cpp:static const Osp::Base::String sVersion(L"2.0" );
  2. ./src/component/KTCacheManager.cpp:static const Osp::Base::String sVersion(L"2.0" );
  3. ./src/component/KTImageDownloader.cpp:static const Osp::Base::String sVersion(L"2.0" );
  4. ./src/component/KTRss.cpp:static const Osp::Base::String sVersion(L"2.0" );
  5. ./src/component/KTUtility.cpp:static const Osp::Base::String sVersion(L"1.0" );


 
Il me semble que l'on peut ajouter une option à grep pour ne pas afficher le chemin mais juste le fichier mais ensuite je devrais bien faire un sed pour récupérer le nom du fichier et la version associer et alors là mes compétences s'arrête.
Quelqu'un pourrait t'il m'aider sur ce point.
Merci d'avance pour vos réponses.
 

Reply

Marsh Posté le 11-01-2011 à 17:01:31   

Reply

Marsh Posté le 11-01-2011 à 17:13:12    

tu peux rajouter à ta ligne:

Code :
  1. find -name *.cpp | xargs grep "sVersion(L" | sed "s/.*\/\(.*\.cpp\).*\"\(.*\)\".*/\1 \2/"

ca devrait faire a peu près ce que tu veux...

Reply

Marsh Posté le 11-01-2011 à 17:20:20    

Bonjour et merci pour ta réponse plus que rapide.
En effet ta proposition marche parfaitement.
 
Mais j'aimerais bien comprendre le sed qui m'a toujours été abstrait.
pourrais tu expliquer rapidement les paramètres du sed si ce n'est pas trop abuser.

Reply

Marsh Posté le 11-01-2011 à 17:31:48    

alors, en gros la syntaxe de sed (utilisé de cette manière), c'est:

Code :
  1. sed "s/chaine_a_remplacer/chaine_de_remplacement/"
 

le s veut dire substitute, donc indique un remplacement... (parce qu'on peut faire aussi plein de trucs, des print, des delete, etc.)

 

ici, je recherche la chaine .*\/\(.*\.cpp\).*\"\(.*\)\".* et je la remplace par \1 \2.

 
  • .*\/ le point c'est n'importe quel caractère, l'étoile veut dire: 0 ou n fois, et \/ parce que je cherche un slash.
  • \(.*.cpp\) quand tu as des parenthèses échappées, c'est pour mettre en mémoire une partie de la chaine, c'est pour ca que dans la seconde partie j'utilise \1 et \2, donc après avoir cherché des trucs puis un slash, j'isole le nom du fichier qui est .*\.cpp (note que j'échappe le point avec \.)
  • .*\" je cherche n'importe quoi jusqu'a une guillemet
  • \(.*\) je met en variable \2 jusqu'a la prochaine guillemet
  • \".* et enfin je termine ma chaine avec tout ce qu'on trouve après la seconde guillemet.


c'est pas hyper compliqué, faut connaitre la base des regexp, comprendre l'esprit et après être méthodique avec les expressions régulières... après si ca se trouve il ya mille fois plus simple pour faire la même chose, avec un autre sed, avec awk, etc.


Message édité par pataluc le 11-01-2011 à 17:32:57
Reply

Marsh Posté le 11-01-2011 à 17:41:26    

Merci encore pour ton aide,
En espérant que se sujet serve à d'autres.

Reply

Marsh Posté le 11-01-2011 à 17:44:28    

pas de souci.

 

et pour le reste: google "man sed" ! :jap:


Message édité par pataluc le 11-01-2011 à 17:44:42
Reply

Marsh Posté le 11-01-2011 à 21:02:05    

Pour simplifier les choses, j'aime bien tenter de limiter le nombre de caractère spéciaux échapés pour améliorer la lisibilité.

 

Ainsi :

find -name *.cpp | xargs grep "sVersion(L" | sed 's#.*/(.*\.cpp).*"(.*)".*#\1 \2#"

 

Devrait donner la même chose en (un peu) plus lisible. :)
Par contre ce que je n'ai pas bien compris, c'est pourquoi les parenthèses sont échappées de base, pataluc. :??:

 

Sinon les explications de pataluc restent applicables, ce que j'ai modifié :

  • le premier caractère suivant le "s", dans sed, indique le séparateur entre "chaîne recherchée" et "chaîne de remplacement". Ici, un #, parce que je sais que je vais mettre des / dans ma chaîne recherchée. En mettant un dièse plutôt qu'un slash, ça me permet d'écrire "/" au lieu de "\/"
  • j'ai mis l'expression régulière entre apostrophes, plutôt qu'entre guillemets. Ici encore, c'est parce que j'aurai des guillemets dans ma chaîne recherchée, je change donc de délimiteur (le shell autorise l'apostrophe ou le guillemet, avec une signification différente pour les deux) pour pouvoir écrire " au lieu de \".


Message cité 1 fois
Message édité par Elmoricq le 11-01-2011 à 21:07:01
Reply

Marsh Posté le 12-01-2011 à 00:37:15    

Elmoricq a écrit :

Par contre ce que je n'ai pas bien compris, c'est pourquoi les parenthèses sont échappées de base, pataluc. :??:

il me semblait que c'était nécessaire... en tout cas ca marche avec, et si je les mets pas: "sed: -e expression #1, char 31: invalid reference \2 on `s' command's RHS"
 
mais sinon, effectivement avec le # et les quotes c'est déja plus lisible...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed