Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 07/01/2016, à 18:11

Tenebrae

Remplacement récurrent

Bonjour,

J'ai un fichier de log dont je dois remplacer la "2eme colonne" dont les lignes ressemble à :

"000024ca600534489abaa2ee0ed09cd1";"Mozilla/5.0 (Linux; Android 5.0; HUAWEI GRA-L09 Build/HUAWEIGRA-L09) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36"
"00026f1e5082b6a2d9f7847f5b8faa0a";"Mozilla/5.0 (Linux; Android Android 5.0.2; 6045Y orange Build/LRX21E) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/38.0.0.0 Mobile Safari/537.36"
"0002dffceb885e4b4a1ce4539132f4f7";"Mozilla/5.0 (iPad; CPU OS 9_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13C75 Safari/601.1"
"000365c8121661a28ee750d4626c206d";"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36"
"00041b6a344e95fe6a61765f54ccdcb7";"Mozilla/5.0 (Windows NT 5.1; rv:43.0) Gecko/20100101 Firefox/43.0"

Je dois obtenir ceci :

"000024ca600534489abaa2ee0ed09cd1";"Linux"
"00026f1e5082b6a2d9f7847f5b8faa0a";"Linux"
"0002dffceb885e4b4a1ce4539132f4f7";"iPad Mac OS"
"000365c8121661a28ee750d4626c206d";"Windows 10"
"00041b6a344e95fe6a61765f54ccdcb7";"Windows XP"

J'arrive à obtenir le résultat désiré en ulitisant

while read line ;do
   local field_1=$( echo "${line}" | awk -F '";"' -v OFS=';' '{print $1}' | sed 's/\"//' );
   local field_2=$( echo "${line}" | awk -F '";"' -v OFS=';' '{print $2}' | sed 's/\"//' );
   case $field_2 in
        *"Windows NT 10"*)  sSysteme="Windows 10" ;;
        *"Windows NT 6.4"*) sSysteme="Windows 10" ;;
        *"Windows NT 6.3"*) sSysteme="Windows 8.1" ;;
        *"Windows NT 6.2"*) sSysteme="Windows 8" ;;
        *"Windows NT 6.1"*) sSysteme="Windows Seven" ;;
        *"Windows NT 6.0"*) sSysteme="Windows Vista" ;;
        *"Windows NT 5.2"*) sSysteme="Windows Server 2003" ;;
        *"Windows NT 5.1"*) sSysteme="Windows XP" ;;
        *"Windows NT 5.0"*) sSysteme="Windows 2000" ;;
        *"Windows NT"*) sSysteme="Windows NT" ;;
        *"Windows 98"*) sSysteme="Windows 98" ;;
        *"iPhone OS"*) sSysteme="iPhone Mac OS" ;;
        *"iPad"*) sSysteme="iPad Mac OS" ;;
        *"Macintosh"*) sSysteme="Intel Mac OS" ;;
        *"Android"*) sSysteme="Adroid" ;;
        *"SunOS"*) sSysteme="Sun OS" ;;
        *"Fedora"*) sSysteme="Fedora" ;;
        *"Haiku"*) sSysteme="Haiku" ;;
        *"Ubuntu"*) sSysteme="Linux Ubuntu" ;;
        *"Window"*) sSysteme="Windows" ;;
        *"iPhone"*) sSysteme="iPhone" ;;
        *"Mac"*) sSysteme="Mac OS" ;;
        *"Linux"*) sSysteme="Linux" ;;
        *) sSysteme="inconnu" ;;
   esac
   echo "\"${field_1}\";\"${sSysteme}\"" >> "${sTempFile}"
done < "${sOutputFile}"

Comme vous vous en doutez niveau performance c'est assez dégradé.

Y aurait-il un moyen de parvenir au même résultat avec un SED par exemple?

Merci de votre réponse.

Merci d'utiliser les balises code pour insérer les lignes de retours de commandes. Merci.

Dernière modification par Ayral (Le 07/01/2016, à 22:46)

Hors ligne

#2 Le 07/01/2016, à 18:40

Watael

Re : Remplacement récurrent

salut,

Comme vous vous en doutez niveau performance c'est assez dégradé.

oui, trop de commandes externes !

while IFS=; read -a fields
do
   case
   ...
   esac
   echo "${fields[0]};\"$sSsyteme\""
done < fichier.log

Dernière modification par Watael (Le 07/01/2016, à 18:57)


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#3 Le 07/01/2016, à 21:49

tiramiseb

Re : Remplacement récurrent

Attention, il y a des ";" dans les champs.

Il semble fort que ce fichier est au format CSV...
Pourquoi ne pas utiliser des outils qui savent lire nativement du CSV ?

Pour ma part je ferais ça en Python, parce que je connais ce langage... mais il y a d'autres solutions pour lire du CSV...

Hors ligne

#4 Le 07/01/2016, à 22:23

tiramiseb

Re : Remplacement récurrent

Je réitère ma suggestion : autant utiliser un soft qui sait lire le CSV...

Hors ligne

#5 Le 07/01/2016, à 22:27

Watael

Re : Remplacement récurrent

Attention, il y a des ";" dans les champs.

ah, oui. sad

c'est pas grave. il n'y en a pas dans le premier champ, et on ne réutilise que ce premier champ.

le tableau n'est pas indispensable, on peut faire ça sur deux variables :

while IFS=';' read first rest; do :whatever with $first; done <fichier

EDIT: oops, j'ai supprimé un premier jet.

autant utiliser un soft qui sait lire le CSV...

par exemple...

Dernière modification par Watael (Le 07/01/2016, à 22:29)


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#6 Le 07/01/2016, à 22:39

tiramiseb

Re : Remplacement récurrent

Approche très simpliste, il y a probablement moyen d'améliorer les perfs...

#!/usr/bin/env python

import csv

matches = [
    ("Windows NT 10", "Windows 10"),
    ("Windows NT 6.4", "Windows 10"),
    ("Windows NT 6.3", "Windows 8.1"),
    ("Windows NT 6.2", "Windows 8"),
    ("Windows NT 6.1", "Windows Seven"),
    ("Windows NT 6.0", "Windows Vista"),
    ("Windows NT 5.2", "Windows Server 2003"),
    ("Windows NT 5.1", "Windows XP"),
    ("Windows NT 5.0", "Windows 2000"),
    ("Windows NT", "Windows NT"),
    ("Windows 98", "Windows 98"),
    ("iPhone OS", "iPhone Mac OS"),
    ("iPad", "iPad Mac OS"),
    ("Macintosh", "Intel Mac OS"),
    ("Android", "Adroid"),
    ("SunOS", "Sun OS"),
    ("Fedora", "Fedora"),
    ("Haiku", "Haiku"),
    ("Ubuntu", "Linux Ubuntu"),
    ("Window", "Windows"),
    ("iPhone", "iPhone"),
    ("Mac", "Mac OS"),
    ("Linux", "Linux"),
    ]

with open('file.csv') as csvfile:
    lines = csv.reader(csvfile, delimiter=';')
    for row in lines:
        system="inconnu"
        for match in matches:
            if match[0] in row[1]:
                system = match[1]
                break
        print '"{}":"{}"'.format(row[0], system)

Dernière modification par tiramiseb (Le 07/01/2016, à 22:42)

Hors ligne

#7 Le 07/01/2016, à 23:52

Watael

Re : Remplacement récurrent

en bricolant un tout petit peu (parce que le Field Separator crée un premier champ vide), tout en Gawk :

gawk -F'(";")|"' '{switch($3){ case /.*Windows.*/: sSys="W$";break; default: sSys="default";break};print "\""$2"\";\""sSys"\""}' fichierCSV.log 
"000024ca600534489abaa2ee0ed09cd1";"default"
"00026f1e5082b6a2d9f7847f5b8faa0a";"default"
"0002dffceb885e4b4a1ce4539132f4f7";"default"
"000365c8121661a28ee750d4626c206d";"W$"
"00041b6a344e95fe6a61765f54ccdcb7";"W$"

Dernière modification par Watael (Le 08/01/2016, à 00:31)


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#8 Le 08/01/2016, à 00:10

Watael

Re : Remplacement récurrent

hmmf sad le FS ne fait pas exactement ce que je veux/pense.
je reviens...

edit :

-F '"|(";")'

à confirmer...

edit2:
le FS est mieux (je corrige dans mon post précédent), mais pas moyen, apparemment, de se défaire de ce premier champ inutile. on conserve un décalage dans la numérotation des champs utiles. hmm

edit3:
j'm'em... avec les guillemets, mais puisqu'il doivent apparaître à la sortie, autant ne pas s'en préoccuper :

gawk 'BEGIN{FS=OFS=";"}{switch($2){ case /.*Windows.*/: new="\"W$\"";break; default: new="\"default\"";break;} print $1,new}'

Dernière modification par Watael (Le 08/01/2016, à 16:45)


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#9 Le 08/01/2016, à 07:25

tiramiseb

Re : Remplacement récurrent

Watael: ou alors on lit le format CSV... smile
... et là forcément ça marche à la perfection !

Dernière modification par tiramiseb (Le 08/01/2016, à 07:25)

Hors ligne

#10 Le 08/01/2016, à 07:31

tiramiseb

Re : Remplacement récurrent

(au fait, Tenebrae, sur iPad et iPhone le système est iOS et sur les Mac le système est "OS X" et non "Mac OS")

Hors ligne

#11 Le 08/01/2016, à 09:22

Compte anonymisé

Re : Remplacement récurrent

sinon avec cut ça peut aussi être pas mal pour lire le csv.

exemple :

   local field_1=$( echo "${line}" | awk -F '";"' -v OFS=';' '{print $1}' | sed 's/\"//' );
   local field_2=$( echo "${line}" | awk -F '";"' -v OFS=';' '{print $2}' | sed 's/\"//' );

...

echo "\"${field_1}\";\"${sSysteme}\"" >> "${sTempFile}"

deviendrait :

field_1=$(echo "${line}" | cut -f 1 -d ";")
field_2=$(echo "${line}" | cut -f 2,3 -d ";")

...

echo ${field_1}";\"${sSysteme}\"" >> "${sTempFile}"

(je sens que mon post va se faire clasher smile)

Dernière modification par Compte anonymisé (Le 08/01/2016, à 09:37)

#12 Le 08/01/2016, à 09:26

tiramiseb

Re : Remplacement récurrent

Anonyme68: non ça ne marchera pas car il y a des ";" dans le second champ : là tu vires tout ce qui se trouve après le deuxième ";"...

Hors ligne

#13 Le 08/01/2016, à 09:32

Compte anonymisé

Re : Remplacement récurrent

en effet, j'ai remplacé pour que ça fonctionne.

Enfin c'est juste à titre d'information, la solution de Watael en post #7 est pas mal aussi.

#14 Le 08/01/2016, à 09:38

tiramiseb

Re : Remplacement récurrent

... pourquoi personne ne dit que ma solution propre en #6 est pas mal ? ... :'(

Hors ligne

#15 Le 08/01/2016, à 09:53

Tenebrae

Re : Remplacement récurrent

Merci pour toute vos réponses.
Je vais testé un peu tout ça. smile

Hors ligne

#16 Le 08/01/2016, à 09:56

claudius01

Re : Remplacement récurrent

Bonjour,

Si si tiramiseb, elle très propre ta solution en #6 et qui plus est très évolutive, mais il semble que les intervenants se limitent à du script shell en excluant le Python.

Personnellement dans ce genre de situation et car je considère le format CSV comme propriétaire, je transforme les données à traiter dans un format XML (comme Convert CSV to XML en autre) et après j'ai toute latitude pour choisir le langage + les outils idoines que j'estime appropriés et surtout que je maîtrise en écrivant le minimum de code...

Dernière modification par claudius01 (Le 08/01/2016, à 09:56)

Hors ligne

#17 Le 08/01/2016, à 09:59

tiramiseb

Re : Remplacement récurrent

il semble que les intervenants se limitent à du script shell

Ce qui est dommage, car ça ne simplifie pas la vie de faire des scripts compliqués comme ça smile

car je considère le format CSV comme propriétaire

'faut pas abuser non plus, le CSV est quand même plutôt ouvert comme format smile
Transformer en XML, c'est pas sûr que ce soit le plus facile big_smile

Hors ligne

#18 Le 08/01/2016, à 10:04

claudius01

Re : Remplacement récurrent

tiramiseb a écrit :

...
Faut pas abuser non plus, le CSV est quand même plutôt ouvert comme format

Je te l'accorde, mais ma démarche sera strictement la même avec d'autres formats plus ou moins "propriétaires"...

Hors ligne

#19 Le 08/01/2016, à 10:09

tiramiseb

Re : Remplacement récurrent

En même temps, vouloir bosser en XML, faut être maso... big_smile
JSON ftw !

(mais bon, là on digresse...)

Dernière modification par tiramiseb (Le 08/01/2016, à 10:09)

Hors ligne

#20 Le 08/01/2016, à 10:15

Tenebrae

Re : Remplacement récurrent

claudius01 a écrit :

Bonjour,

Si si tiramiseb, elle très propre ta solution en #6 et qui plus est très évolutive, mais il semble que les intervenants se limitent à du script shell en excluant le Python.

Personnellement dans ce genre de situation et car je considère le format CSV comme propriétaire, je transforme les données à traiter dans un format XML (comme Convert CSV to XML en autre) et après j'ai toute latitude pour choisir le langage + les outils idoines que j'estime appropriés et surtout que je maîtrise en écrivant le minimum de code...

Bonjour,

Dans mon cas, pas le choix d'utiliser autre chose que Shell et CSV (format du fichier à traiter et renvoyé)....
De plus, je ne maitrise pas bien Shell et pas du tout Python tongue

Hors ligne

#21 Le 08/01/2016, à 10:24

tiramiseb

Re : Remplacement récurrent

pas le choix d'utiliser autre chose que Shell

Pourquoi donc ? Python est installé par défaut sur la plupart des distributions, si pas toutes...

Et puis je rappelle que dans ton premier script tu utilises trois choses : un shell, awk et sed. Ce sont trois outils indépendants, dont les versions et les arguments peuvent changer.
Dans mon script, on utilise un seul langage, qui ne va pas changer... smile

La solution en #7 de Watael, par exemple, ce n'est pas non plus un shellscript.
Il appelle juste gawk (donc il faut que gawk soit installé sur la machine) pour exécuter un script inline. Il aurait très bien pu mettre le contenu de sa chaîne de caractères dans un fichier et mettre gawk dans le shebang de ce fichier (et ça aurait été bien plus propre).

Donc à mon avis, ta contrainte est mal énoncée smile

Hors ligne

#22 Le 08/01/2016, à 11:09

claudius01

Re : Remplacement récurrent

tiramiseb a écrit :

Pourquoi donc ? Python est installé par défaut sur la plupart des distributions, si pas toutes...

Et puis je rappelle que dans ton premier script tu utilises trois choses : un shell, awk et sed. Ce sont trois outils indépendants, dont les versions et les arguments peuvent changer.
Dans mon script, on utilise un seul langage, qui ne va pas changer...

+1 pour tiramiseb, car le mélange et l'utilisation de plusieurs outils au gré des besoins est une mauvaise chose.

Dès lors que le format pivot des données (ici le CSV et pour moi le XML voire JSON ;-) est arrêté, se concentrer sur un et un seul langage et leurs outils associés pour éviter le plat de nouilles qui conduit à une programmation itérative, interminable, non évolutive et surtout "inmaintenable"...

Si le bash et le csv sont l'expression du besoin, s'orienter vers un outil ad hoc comme bash csv tool avec en particulier csvkit.

A suivre...

Dernière modification par claudius01 (Le 08/01/2016, à 11:17)

Hors ligne

#23 Le 08/01/2016, à 11:17

tiramiseb

Re : Remplacement récurrent

claudius01 : as-tu conscience que l'outil que tu proposes, csvkit, est un logiciel supplémentaire à installer, codé en Python, qui s'appuie précisément sur le module standard csv que je propose d'utiliser ? smile

Dernière modification par tiramiseb (Le 08/01/2016, à 11:19)

Hors ligne

#24 Le 08/01/2016, à 11:20

tiramiseb

Re : Remplacement récurrent

Plutôt que de dire « utilise bash et installe un logiciel de plusieurs centaines de lignes en python pour parser ton csv et ensuite le traîter en shellscript », je préfère dire « fais un script de 20 lignes exclusivement en python, sans nécessiter quoi que ce soit d'autre » wink

Hors ligne

#25 Le 08/01/2016, à 11:20

claudius01

Re : Remplacement récurrent

J'en suis conscient @ "as-tu conscience que l'outil que tu proposes, csvkit, ..." mais je tiens compte de: "De plus, je ne maitrise pas bien Shell et pas du tout Python" écrit par notre ami Tenebrae à qui on pourrait répondre et conseiller: C'est l'occasion de s'y mettre [à Python] mais cela ne dépend pas de nous...

Dernière modification par claudius01 (Le 08/01/2016, à 11:24)

Hors ligne