Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Représenter un arbre sous forme de liste

18 réponses
Avatar
Olivier Miakinen
Bonjour,

Me voici avec un nouveau challenge. Cette fois, je n'ai besoin de le
faire fonctionner que sur une seule machine, alors cela peut aussi
bien être en perl qu'en awk, ou tout autre outil dont je pourrais
disposer.

Noter que s'il n'y a pas de solution simple avec les outils existants
je pourrai toujours écrire un programme en C (je sais le faire, c'est
juste que ça me prendra un peu plus de temps). Mais je fais confiance
à l'ingéniosité des lecteurs de ce groupe, je vous ai déjà vu me
proposer des solutions géniales.

J'ai un fichier qui ressemble à ceci (je coupe pas mal de lignes, c'est
juste pour un exemple) :
=========================================================================
+-1 -
+-3 -
+-6 -
+-1 -
+-2 -
| +-1 -
| +-2 GENERATE oid interfaces
| | +-1 GENERATE attribute ifNumber
| | +-2 ignore table ifTable
| | +-1 GENERATE entry ifEntry
| | +-1 GENERATE attribute ifIndex (index)
| | +-2 GENERATE attribute ifDescr
| | +-3 GENERATE attribute ifType
| | +-4 GENERATE attribute ifMtu
| +-31 ignore module-identity ifMIB
| +-1 GENERATE oid ifMIBObjects
| | +-1 ignore table ifXTable
| | | +-1 GENERATE entry ifXEntry
| | | +-1 GENERATE attribute ifName
| | | +-2 GENERATE attribute ifInMulticastPkts
| | | +-3 GENERATE attribute ifInBroadcastPkts
| | | +-4 GENERATE attribute ifOutMulticastPkts
| | | +-5 GENERATE attribute ifOutBroadcastPkts
| | | +-6 ignore attribute ifHCInOctets (counter64)
| | | +-7 ignore attribute ifHCInUcastPkts (counter64)
| | +-2 ignore table ifStackTable
| +-2 ignore oid ifConformance
| +-1 ignore oid ifGroups
| | +-1 ignore object-group ifGeneralGroup
| | +-2 ignore object-group ifFixedLengthGroup
| +-2 ignore oid ifCompliances
| +-1 ignore module-compliance ifCompliance
| +-2 ignore module-compliance ifCompliance2
| +-3 ignore module-compliance ifCompliance3
+-6 -
+-3 -
+-1 -
+-1 -
+-5 -
+-3 GENERATE notification-type linkDown
+-4 GENERATE notification-type linkUp
=========================================================================

On y voit un arbre où chaque n½ud est numéroté, le nombre de caractères
(espaces, "|", '+' ou '-') précédant chaque numéro valant deux fois la
profondeur de l'arbre. Après le numéro, on trouve des espaces, puis
soit un caractère '-', soit un mot-clé 'ignore' ou 'GENERATE' suivi
d'un type d'objet puis du nom de l'objet.

En gros, je ne m'intéresse qu'aux lignes avec GENERATE, mais pour
chacune de ces lignes je voudrais afficher la liste de tous les
nombres depuis la racine de l'arbre, comme ceci :
=========================================================================
(1 3 6 1 2 1 2 ) GENERATE oid interfaces
(1 3 6 1 2 1 2 1 ) GENERATE attribute ifNumber
(1 3 6 1 2 1 2 2 1 ) GENERATE entry ifEntry
(1 3 6 1 2 1 2 2 1 1 ) GENERATE attribute ifIndex (index)
(1 3 6 1 2 1 2 2 1 2 ) GENERATE attribute ifDescr
(1 3 6 1 2 1 2 2 1 3 ) GENERATE attribute ifType
(1 3 6 1 2 1 2 2 1 4 ) GENERATE attribute ifMtu
(1 3 6 1 2 1 31 1 ) GENERATE oid ifMIBObjects
(1 3 6 1 2 1 31 1 1 1 ) GENERATE entry ifXEntry
(1 3 6 1 2 1 31 1 1 1 1 ) GENERATE attribute ifName
(1 3 6 1 2 1 31 1 1 1 2 ) GENERATE attribute ifInMulticastPkts
(1 3 6 1 2 1 31 1 1 1 3 ) GENERATE attribute ifInBroadcastPkts
(1 3 6 1 2 1 31 1 1 1 4 ) GENERATE attribute ifOutMulticastPkts
(1 3 6 1 2 1 31 1 1 1 5 ) GENERATE attribute ifOutBroadcastPkts
(1 3 6 1 6 3 1 1 5 3 ) GENERATE notification-type linkDown
(1 3 6 1 6 3 1 1 5 4 ) GENERATE notification-type linkUp
=========================================================================

Comme je le disais, en C je sais récupérer le nombre de caractères
d'indentation grâce à sscanf et « %* », et du coup construire petit
à petit la liste des entiers :
sscanf(line, "%*[ |+-]%n%u %s", &indent, &subid, genstatus);

Mais en shell (ou awk, perl, etc.) ?

Cordialement,
--
Olivier Miakinen

8 réponses

1 2
Avatar
Antoine Leca
Cyrille Lefevre écrivit :
GNU bash, version 4.1.10(4)-release (i686-pc-cygwin)


^^^^^^
Euh, là tu as rajouté une couche qui ne doit sûrement pas aider aux
performances relatives de bash vis-à-vis de perl ou python ;-)


Antoine
Avatar
Stephane Chazelas
2012-04-25 04:23:08 +0200, Cyrille Lefevre:
Le 24/04/2012 14:26, Stephane Chazelas a écrit :
>2012-04-24 11:17:21 +0200, Olivier Miakinen:
>[...]
>>J'ai un fichier qui ressemble à ceci (je coupe pas mal de lignes, c'est
>>juste pour un exemple) :
>>======================================================================== > >>+-1 -
>> +-3 -
>> +-6 -
>> +-1 -
>> +-2 -
>> | +-1 -
>> | +-2 GENERATE oid interfaces
>> | | +-1 GENERATE attribute ifNumber
>> | | +-2 ignore table ifTable
>> | | +-1 GENERATE entry ifEntry
>> | | +-1 GENERATE attribute ifIndex (index)
>[...]
>>nombres depuis la racine de l'arbre, comme ceci :
>>======================================================================== > >>(1 3 6 1 2 1 2 ) GENERATE oid interfaces
>>(1 3 6 1 2 1 2 1 ) GENERATE attribute ifNumber
>>(1 3 6 1 2 1 2 2 1 ) GENERATE entry ifEntry
>>(1 3 6 1 2 1 2 2 1 1 ) GENERATE attribute ifIndex (index)
>[...]
>
>perl -lne 'if (/(.*?)(d+)s+((S+).*)/) {$n=length($1)/2;
> $a[$n]=$2; print "(@a[1..$n]) $3" if $4 eq "GENERATE"}'

Bonjour,

la même en awk '
match($0, /[0-9]+/) {
n = (RSTART-1) / 2
a[n] = substr($0, RSTART, RLENGTH)
}
/GENERATE/ {
r = ""; s = "("
for (i = 1; i <= n; i++) {
r = r s a[i]
s = " "
}
r = r " )"
print r substr($0, RSTART + RLENGTH + 1)
}
'

bon, sur ce coup là, j'ai tout simplement passé le code perl au
compilo perl2awk %^)

c'est quand même plus simple que du python ou du perl, et plus
portable surtout ;^p


[...]

Plus simple, je ne trouve pas, plus portable, je ne crois pas.
Mon code marche avec toutes les versions de perl et perl est
partout a part sur certains systemes embarqués peut-etre de nos
jours.

Alors que ton code ne marche pas avec le awk original (comme le
/usr/bin/awk de Solaris) ou les awks /reduits/ de certains
systemes embarqués.

Une entree telle que:
-+2 ignore attribute GENERATE

posera probleme aussi.

[...]
tout d'abord, mir-ksh (aka pd-ksh)


[...]

mksh est basé sur pdksh mais n'est pas pdksh.

[...snip...]

Tu t'ennuies un peu Cyrille, non ? ;-)

--
Stephane
Avatar
Cyrille Lefevre
Le 25/04/2012 10:05, Antoine Leca a écrit :
Cyrille Lefevre écrivit :
GNU bash, version 4.1.10(4)-release (i686-pc-cygwin)


^^^^^^
Euh, là tu as rajouté une couche qui ne doit sûrement pas aider a ux
performances relatives de bash vis-à-vis de perl ou python ;-)



Bonjour,

pas si sur, ce n'est qu'une boucle while read après tout, ce qui n'est
pas du tout le fort de bash.

Cordialement,

Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%
supprimer "%nospam% et ".invalid" pour me repondre.
Avatar
Cyrille Lefevre
Le 25/04/2012 11:06, Stephane Chazelas a écrit :
2012-04-25 04:23:08 +0200, Cyrille Lefevre:


<snip>
bon, sur ce coup là, j'ai tout simplement passé le code perl au
compilo perl2awk %^)

c'est quand même plus simple que du python ou du perl, et plus
portable surtout ;^p


[...]

Plus simple, je ne trouve pas, plus portable, je ne crois pas.
Mon code marche avec toutes les versions de perl et perl est
partout a part sur certains systemes embarqués peut-etre de nos
jours.



Bonjour,

hé! fait pas la geule, je plaisantais :-)

Alors que ton code ne marche pas avec le awk original (comme le
/usr/bin/awk de Solaris) ou les awks /reduits/ de certains
systemes embarqués.



d'un autre côté, pas grand chose ne tourne sur le awk de base de
solaris, raison pour laquelle tout le monde utilise nawk que tu trouves
également sur les autres os proprio sous de doux nom de awk :-)

Une entree telle que:
-+2 ignore attribute GENERATE

posera probleme aussi.



le awk marche :-P

v2$ ./snmp.awk x.txt
(2 ) ignore attribute GENERATE

[...]
tout d'abord, mir-ksh (aka pd-ksh)


[...]

mksh est basé sur pdksh mais n'est pas pdksh.



mouai, tu chipottes là, non ?
à ce tarif là, l'ash de freebsd n'a plus rien à voir non plus avec
sa version d'origine tellement il a été modifié, me trompe-je ?

[...snip...]

Tu t'ennuies un peu Cyrille, non ? ;-)



nan, nan, j'me change les idées...
c'est-y pas cool de trouver la même solution dans plusieurs languages e t
de comparer les perfs résultantes...

Cordialement,

Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%
supprimer "%nospam% et ".invalid" pour me repondre.
Avatar
Stephane Chazelas
2012-04-25 13:07:50 +0200, Cyrille Lefevre:
[...]
>Une entree telle que:
>-+2 ignore attribute GENERATE
>
> posera probleme aussi.

le awk marche :-P

v2$ ./snmp.awk x.txt
(2 ) ignore attribute GENERATE



Ben non, "ignore" veut dire ignorer la ligne d'apres les
requirements.

>[...]
>>tout d'abord, mir-ksh (aka pd-ksh)
>[...]
>
>mksh est basé sur pdksh mais n'est pas pdksh.

mouai, tu chipottes là, non ?
à ce tarif là, l'ash de freebsd n'a plus rien à voir non plus avec
sa version d'origine tellement il a été modifié, me trompe-je ?



Non, il y a plusieurs variantes de ash qui ont toutes le meme
nom. Et il y a pdksh (toujours maintenu) et plusieurs variantes
(posh, mksh...).


>[...snip...]
>
>Tu t'ennuies un peu Cyrille, non ? ;-)

nan, nan, j'me change les idées...
c'est-y pas cool de trouver la même solution dans plusieurs
languages et de comparer les perfs résultantes...


[...]

Non. c'est boring ;-)

Tiens, une solution sed:

sed '1G;G;s/..(.*n).*n/1 14:47
/;:1
s/^[^0-9]{2}(.*n.*)n([0-9]{1,} )/12
/;t1
s/^([0-9]*) *(.*n.*)n.*/21 /;h;/^GENERATE/!d;s/(.*)n(.*)/(2) 1/'

(je ne m'attends pas a des performances exceptionnelles).

--
Stephane
Avatar
Olivier Miakinen
Le 25/04/2012 11:06, Stephane Chazelas a écrit :

Une entree telle que:
+-2 ignore attribute GENERATE

posera probleme aussi.



Il se trouve qu'une telle entrée ne peut pas exister car les noms
d'attribut commencent tous par une lettre minuscule, au contraire
des syntaxes qui commencent par une majuscule. Mais dans l'absolu
tu as raison : rien dans ma demande ne pouvait laisser deviner
une telle contrainte. Et puis, quoi que ce soit peu probable vu
que le principe est de ne capitaliser que les initiales des mots
autres que le premier, on pourrait avoir une entrée telle que :
+-2 ignore attribute numberOfWordsGENERATE

[...snip...]

Tu t'ennuies un peu Cyrille, non ? ;-)



:-)
Avatar
Cyrille Lefevre
Le 25/04/2012 15:53, Stephane Chazelas a écrit :
2012-04-25 13:07:50 +0200, Cyrille Lefevre:
[...]
Une entree telle que:
-+2 ignore attribute GENERATE

posera probleme aussi.



le awk marche :-P

v2$ ./snmp.awk x.txt
(2 ) ignore attribute GENERATE



Ben non, "ignore" veut dire ignorer la ligne d'apres les
requirements.



ah! àa, && !/ignore/ et hop :-)

[...snip...]

Tu t'ennuies un peu Cyrille, non ? ;-)



nan, nan, j'me change les idées...
c'est-y pas cool de trouver la même solution dans plusieurs
languages et de comparer les perfs résultantes...


[...]

Non. c'est boring ;-)

Tiens, une solution sed:

sed '1G;G;s/..(.*n).*n/1 14:47
/;:1
s/^[^0-9]{2}(.*n.*)n([0-9]{1,} )/12
/;t1
s/^([0-9]*) *(.*n.*)n.*/21 /;h;/^GENERATE/!d;s/(.*)n(.*)/( 2) 1/'

(je ne m'attends pas a des performances exceptionnelles).



Bonjour,

ah! ben, tu vois que toi aussi tu t’ennuies :-))

Cordialement,

Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%
supprimer "%nospam% et ".invalid" pour me repondre.
Avatar
Olivier Miakinen
Le 26/04/2012 14:08, Cyrille Lefevre a écrit :
[...]
Une entree telle que:
+-2 ignore attribute GENERATE

posera probleme aussi.



le awk marche :-P

v2$ ./snmp.awk x.txt
(2 ) ignore attribute GENERATE



Ben non, "ignore" veut dire ignorer la ligne d'apres les
requirements.



ah! àa, && !/ignore/ et hop :-)



Ne marchera pas avec :
+-2 GENERATE attribute ignoreAllTraps

(et oublier un attribut généré aurait été beaucoup plus gênant
pour moi que de voir apparaître un attribut ignoré).
1 2