Aide pour awk!

Bonjour a tous,
merci de bien vouloir m’aider, je galère avec un problème qui sera je pense très simple pour vous…
Je dois récupérer absolument avec la commande AWK un bout de repertoire je m’explique:

/home/titi/toto/

Avec la commande awk doit maider a recuperer "toto"
Qu’elle est la syntaxe??
Merci d’avance!!

Comme ça ? On découpe sur '/' puis on affiche uniquement l'avant dernier élément.

Tu veut que ça puisse fonctionner avec sous sans / à la fin ? Ou tu veut pouvoir l'intégrer à un code existant ? Alors :
[code]awk '{ n=split("/home/titi/toto/", dir, "/"); if(dir[n] == "") { print dir[n-1] } else { print dir[n]; } }'[/code]

Comme ça ? On découpe sur ‘/’ puis on affiche uniquement l’avant dernier élément.

Tu veut que ça puisse fonctionner avec sous sans / à la fin ? Ou tu veut pouvoir l’intégrer à un code existant ? Alors :

[quote=“vinced86”]Bonjour a tous,
merci de bien vouloir m’aider, je galère avec un problème qui sera je pense très simple pour vous…
Je dois récupérer absolument avec la commande AWK un bout de repertoire je m’explique:

/home/titi/toto/

Avec la commande awk doit maider a recuperer "toto"
Qu’elle est la syntaxe??
Merci d’avance!![/quote]

Tu as absolument besoin de awk ? Pourquoi faire compliqué quand on peut faire simple ?

abc="/home/titi/toto/" abc="${abc%/}" # "/home/titi/toto", peu importe si le '/' de fin était présent abc="${abc##*/}" # "toto"

Encore plus simple: basename /home/titi/toto :smiley:

:open_mouth: je ne connaissais même pas
Je viens de voir qu’il existe aussi dirname (coreutils)

Oui, mais…

[code]time find /usr | xargs -l1 basename &>/dev/null

real 0m13.984s
user 0m3.190s
sys 0m10.780s

time for i in $(find /usr); do i=${i%/}; echo ${i##*/} &>/dev/null; done

real 0m1.072s
user 0m0.551s
sys 0m0.442s[/code]

…c’est long.

Mauvais benchmark inverse les deux commandes la différence seras moins grande.

Ah, en effet. Mais ne pas avoir à appeler basename fait quand même une différence d’un facteur 2 (à vue d’oeil), sur mon poste. Bon, oui, c’est moins bien que le facteur 13 :slightly_smiling:

Sur un 2xQuadcore avec du sas :

[code]# time for i in $(du / | cut -f2 2>/dev/null); do i=${i%/}; echo ${i##*/}; done &>/dev/null

real 0m0.249s
user 0m0.108s
sys 0m0.124s

time du / 2>/dev/null | cut -f2 | xargs -l1 basename &>/dev/null

real 0m1.824s
user 0m0.436s
sys 0m1.244s[/code]

Ca fait tout de même une belle différence, mais en effet c’est intéressant que dans le cas ou on réitère beaucoup.

Pour l’explication ça viens de la mise en cache du noyau des informations du système de fichier. Pour s’en convaincre il suffit de lancer deux fois du ou find avec exactement les même arguments.

Le benchmark initial est d’autant plus faux que les éléments à comparer diffèrent.

Pour qu’il soit juste, il faudrait tester :

#/bin/bash
time while read ; do basename "${REPLY}"; done < <(find /usr) >&/dev/null
#et
time while read ; do i="${REPLY%/}"; echo ${i##*/}; done < <(find /usr) >&/dev/null

en effet, le résultat initial tient compte de critères supplémentaires faussant le test :

  • création et suppression de sous processus ayant pour origine l’utilisation du pipe
  • utilisation de xargs donc mise en mémoire/libération d’un programme supplémentaire ainsi que des librairies nécessaires

Par ailleurs, il n’est pas nécessaire d’effectuer de benchmark pour prouver cela : l’utilisation d’outils externes au langage de script contextuel implique des accès disques (recherche des binaires et librairies) et manipulation mémoires (chargement, déchargement) supplémentaires comparé à l’utilisation des builtins. Le temps d’exécution est donc impacté.

L’ensemble des éléments dont tu parle, bien que justes, sont epsilon face à l’accès disque mis en cache (pour ça que j’en ai pas parlé). :slightly_smiling:

Pour ce qui est de l’avantage du builtin face à la commande extérieure, oui c’est plus efficace mais il faut savoir quand les utiliser et quand ne pas les utiliser. Pour des expressions complexes ou combinées sed peut être plus efficace qu’une version en shell qui généreras pleins de variables sh intermédiaire.

Par contre à partir du moment où on utilise un programme extérieure il est bon de lui en faire faire le plus et de limiter leur nombre :

est clairement moins efficace qu’un awk (sans compter que le grep devrait se mettre avant le sed).