Vous n'êtes pas identifié.
Bonjour a tous, je suis venu ici en esperant un petit coup de main
je vous explique tout de suite le probleme : je recupere un fichier d'accounting d'imprimante et je fait divers traitement dessus
seulement je me retrouve bloqué :
j arrive a une ligne de cette forme :
manuel|...........|1|4/17/2008 15:05:02|0.000000|0.000000|0.000000|0.095604|0.000000|0.005946|...........|SGINFO|A4_B|coste
mon probleme est que je dois mettre la date sous cette forme : 2008-4-17 15:05:02 tout en conservant les autres champs afin de l inserer dans un bon format pour ma bd
j'ai teste diverses méthodes et celle qui s'en est le plus rapproche est celle ou je remplace l'espace au centre de la date par un espace suivi d'un delimiteur afin d inverser les champs a ma guise
seul probleme, le nom d'utilisateur, premier champ, peut lui aussi possédé un espace ex : "Vincent Motto-Ros"
je ne vois plus comment m'en dépatouiller et cela me bloque pour la suite du traitement ( je peux charger la date en tant que chaine de caractere pour faciliter mais le probleme c est que par la suite je vais avoir besoin de selectionner des lignes en fonction de la date, donc pas possible)
si quelqu'un pouvait m'aider ce serait super
Hors ligne
Salut, fais le avec les expressions régulières (rationnelles)
un truc du style:
TEST="manuel|...........|1|4/17/2008 15:05:02|0.000000|0.000000|0.000000|0.095604|0.000000|0.005946|...........|SGINFO|A4_B" echo $TEST | sed "s%\(.*\)|\([[:digit:]]*\)/\([[:digit:]]*\)/\([[:digit:]]*\) \(.*\)%\\1|\\4-\\2-\\3 \\5%"
Et la petite vérif du sed au-dessus:
$ echo $TEST manuel|...........|1|4/17/2008 15:05:02|0.000000|0.000000|0.000000|0.095604|0.000000|0.005946|...........|SGINFO|A4_B $ echo $TEST | sed "s%\(.*\)|\([[:digit:]]*\)/\([[:digit:]]*\)/\([[:digit:]]*\) \(.*\)%\\1|\\4-\\2-\\3 \\5%" manuel|...........|1|2008-4-17 15:05:02|0.000000|0.000000|0.000000|0.095604|0.000000|0.005946|...........|SGINFO|A4_B
J'ai pondu l'expression rapidement.. faudrait bien vérifier et(ou) améliorer.
Hors ligne
je te remercie je te tiendrais au courant lundi sur l'évolution du problème
Hors ligne
juste un tit mot pour te dire que ca marchait à la perfection ; toutefois serait il possible que tu m'expliques en détail la commande :
en effet je risque d'avoir a faire plusieurs commandes rationnelles et je manque cruellement d'experience avec sed : ne comprenant pas toutes les subtilités je serais totalement incapable d'exploiter une telle ligne
merci bien
Hors ligne
Pour t'expliquer au complet les expressions rationnelle il me faudrait écrire un livre..
alors je vais me contenter de t'expliquer juste l'expression que je t'ai proposé. Si tu veux en savoir plus je te conseil de chercher de la doc directement via ton moteur de recherche favoris.
Bref
sed "s%\(.*\)|\([[:digit:]]*\)/\([[:digit:]]*\)/\([[:digit:]]*\) \(.*\)%\\1|\\4-\\2-\\3 \\5%"
man sed
c'est bien aussi.. mais bref ;-)
dans l'exemple il y a cette forme:
sed "s%%%"
qui aurait pu être
sed "s///" ou sed "s###"
peu importe car % ou / ou # sont juste là comme délimiteur entre ce qu'il doit chercher et avec quoi il le change.
en résumé c'est sed "s/qui/par quoi/"
le 's' il dit qu'on va faire un remplacement
donc si tu fais
echo "lol lol" | sed "s/lol/mdr/"
ca va remplacer le premier lol par mdr sur la ligne donc : "mdr lol"
si tu fais
echo "lol lol" | sed "s/lol/mdr/g"
ca va remplacer tous les lol par mdr tjrs sur la ligne donc : "mdr mdr"
si tu fais
cat mon_fichier | sed "s/lol/mdr/"
ca va remplacer le premier lol trouvé sur chaque ligne. et avec g sur toute la ligne..
bref on pourrait faire
sed "s/foo/bar/" monfichier
c'est plus propre et meme rajouter -i pour éditer sur place et pas rediriger dans le stdout..
mais bon je te laisse lire le man..
ensuite un truc sympa c'est les expressions rationelles.. alors je vais directement t'expliquer tout l'exemple en une fois pour pas passer des heures..
donc
sed "s%\(.*\)|\([[:digit:]]*\)/\([[:digit:]]*\)/\([[:digit:]]*\) \(.*\)%\\1|\\4-\\2-\\3 \\5%"
découpons le problème
\(.*\)
|
([[:digit:]]*\)
/
\([[:digit:]]*\)
/
\([[:digit:]]*\)
(y a un espace ici)
\(.*\)
les \ sont juste la pour protéger les (), en fait ici les parenthèse sont utiles pour dire ce que l'on veut récupérer dans la partie de droite du "s//la partie ici/"
le point veut dire n'importe quel caractère.. donc .* veut dire n'importe quel caractère qu'il soit présent 0 fois ou plusieurs fois.. y a plein de variantes avec +, ? .. bref
[[:digit:]] veut dire qu'on veut un chiffre, à la place on aurait pu écrire [0-9] qui veut dire les chiffres de 0 à 9.. on aurait même pu écrire [0123456789]
donc [[:digit:]]* signifie 0 fois ou plusieurs chiffres
Je te laisse réfléchir un peu maintenant.. encore juste une info concernant les parenthèses..
dans la partie de droite du sed tu vois %\\1|\\4-\\2-\\3 \\5%
en fait le \\1 fait appelle au premier groupe de parenthèse, le \\2 au deuxième etc..
donc \1 c'est le .* (ce qu'il y a avant la date)
le \4 c'est l'année
\2 le mois, etc.. ici tu vois bien que j'ai déplacé l'année en première position, le mois en deuxième.. et que j'ai changé les / en -
c'est extrêmement puissant comme système.. tu peux absolument tout faire avec juste les commandes sed, grep et cat.
Hors ligne
bah tu ferais un très bon prof
d'apres ce que je comprend tu cherches l'expression de forme delimiteur suivi par nombre suivi par nombre suivi par nombre ( avec les / entre)
le .* selectionne donc tout ce qui précède puis à la fin tout ce qui suit
et après tu réécris dans l'ordre
j'avais remarque que sed était puissant mais je me doutais pas qu'on puisse faire quelque chose d'apriori si compliqué par quelque chose d'aussi simple
mais toutefois je risque de faire a nouveau appel à tes services pour un problème du même genre mais qui reste compliqué :
lorsque je récupère le fichier la ligne initiale est de cette forme :
8, AppSocket, Gérard, machine.ujf-grenoble.fr, The_Edinburgh_Journal_of_Science.pdf, The_Edinburgh_Journal_of_Science.pdf, 8, 16, 4/18/2008 10:46:57, 4/18/2008 10:49:26, 00:02:29, Plain Paper, A4, 0.2845%, 0.2140%, 0.1804%, 1.3485%, 0.0519%
le délimiteur de base attribuée par l'imprimante est donc la virgule et j'ai donc 18 champs fixe
problème : le 5eme et 6 eme champ, a savoir le nom du fichier imprimé s'avère problématique : j'ai remarqué que certains fichiers imprimés pouvait contenir une virgule ( quelle chance ) je me retrouve donc parfois avec 22 champs ( ou plus ca depend du nombre de virgules )
cela n'empeche pas mon script de tourner mais ces lignes deviennent inexploitables
mon idée serait de supprimer directement ces champs
au debut je pensais réécrire la ligne jusqu'a "machine.ujf" compris , faire un reverse de la ligne puis reecrire jusqu'au dernier chiffre mais je ne sais pas comment faire si jamais le fichier est nommée par un chiffre
Dernière modification par yanimal (20 May 2008 10:48:22)
Hors ligne
facile
une manière de faire (j'ai rajouté exprès plein de virgules dans les noms des fichiers pour prouver que ca marche):
$ TEST="8, AppSocket, Gérard, machine.ujf-grenoble.fr, The_Edin,burgh_Jo,urnal_of_Sc,ience.pdf, The_Edinburgh_,,,Journal_of_Science.pdf, 8, 16, 4/18/2008 10:46:57, 4/18/2008 10:49:26, 00:02:29, Plain Paper, A4, 0.2845%, 0.2140%, 0.1804%, 1.3485%, 0.0519%" $ echo $TEST 8, AppSocket, Gérard, machine.ujf-grenoble.fr, The_Edin,burgh_Jo,urnal_of_Sc,ience.pdf, The_Edinburgh_,,,Journal_of_Science.pdf, 8, 16, 4/18/2008 10:46:57, 4/18/2008 10:49:26, 00:02:29, Plain Paper, A4, 0.2845%, 0.2140%, 0.1804%, 1.3485%, 0.0519% $ echo $TEST | sed "s#\([^,]*,[^,]*,[^,]*,[^,]*\),.*,.*,\([^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*\)#\1, file, file,\2#" 8, AppSocket, Gérard, machine.ujf-grenoble.fr, file, file, 8, 16, 4/18/2008 10:46:57, 4/18/2008 10:49:26, 00:02:29, Plain Paper, A4, 0.2845%, 0.2140%, 0.1804%, 1.3485%, 0.0519%
bien sûr que ,.*,.*, c'est supide, on peut directement écrire .* à la place
mais sinon c'est moins pédagogique
et [^,]* ca veut dire que les caractères peuvent être tout sauf une virgule.. le ^ faisant office de "différent de" dans ce cas précis.. attention car il peut aussi vouloir dire que c'est le début de la ligne.. ca dépend de comment il est utilisé.
Hors ligne
ta commande marche pas mal mais il me reste un problème
dans le cas ou ces fameux noms de fichiers possèdent également d'autres caractères ca a l'air de poser problèmes
genre ":" "\" etc.... ca me parait bizarre
egalement en présence de majuscules ?
lorsque j utilise ta commande voici le genre de noms de fichiers qui restent :
C:Documents and SettingsGra...9cp.defaultCacheB267EF66d01
CJO - Abstract - Effets de réseau dans la science pré-institu...
http://catalogue.bm-grenoble.fr:81/cgi- … 4&s...
La_science_des_pierres_pr__cieuses__appl.pdf
etc ...
serait il possible de readapter pour sauter tout ces caractères ?
Dernière modification par yanimal (21 May 2008 17:51:01)
Hors ligne
donne des exemples de lignes qui soient concrètent..
après le seul problème c'est s'il y a des virgules dans les noms des fichiers.. car il devient impossible de savoir quel virgule fait office de séparateur et lesquels sont dans le nom (c'est pour cela que j'ai forcé "file" à la sortie). Les autres caractères n'ont aucune raisons de poser problème.
Hors ligne
oula c'est moi qui ai du faire le cancre ^^ en traitement local ca fonctione, c'est juste quand je l'incorpore au script que ca deconne ..... j'etudie le probleme et je te tiens au courant
Hors ligne
gros problème type mystère sans réponse ..............
j ai adapté ta requête sous forme de script
voici a quoi il ressemble :
#! /bin/bash
#on efface la precedente trace d'utilisation
rm ./final.txt
while read line
do
var=$(echo "$line")
#echo $var
# expression rationnelle
var2=$(echo $var | sed "s#\([^,]*,[^,]*,[^,]*,[^,]*\),.*,.*,\([^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*\)#\1, file, file,\2#")
#echo $var2
echo "$var2" >> ./final.txt
done < $1
ce script fonctionne parfaitement depuis le bureau quand je l applique sur mon fichier à traiter
problème : j ai donc creer ce script dans mon dossier de traitement et j y fais appel durant les différentes procédures de mon script principal
je l applique toujours sur le fameux fichier à traiter mais la , magie, toutes les lignes ne sont pas traitées : je precise que c est exactement le même algo et exactement le meme fichier source
je me suis donc dis que durant le traitement , le fichier source à traiter etait peut etre encore en cours de traitement
j ai donc bien separer chacune des mes actions par un ";" et separer de plusieurs sleep de 10 sec histoire d'etre sur : mais toujours rien
le script ne veut pas s appliquer sur toutes les lignes
Hors ligne
Oh my god.
sed, par défaut, applique la commande à chaque ligne. Tout cet enrobage est probablement inutile.
#!/bin/bash sed -e "s#\([^,]*,[^,]*,[^,]*,[^,]*\),.*,.*,\([^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*\)#\1, file, file,\2#" "$1" >final.txt
ferait aussi l'affaire. Pour le reste, si tes lignes contiennent des paths à la Windows, il est probable que certains \ soient échappés par les multiples passages dans la commande echo. Il est aussi possible que certains espaces ou méta-caractères soient gobés par le shell, toujours pour la même raison.
En revanche, le "final.txt" est très certainement superflu et introduit un risque supplémentaire, tu peux probablement ajuster ton script principal pour lire dans un pipe à la place.
Hors ligne
BOFH a écrit:
Oh my god.
sed, par défaut, applique la commande à chaque ligne. Tout cet enrobage est probablement inutile.
.
s/probablement/totalement
surtout que dans le deuxième message que j'ai écris dans ce topic j'ai explicitement parlé de ça:
si tu fais
cat mon_fichier | sed "s/lol/mdr/"
ca va remplacer le premier lol trouvé sur chaque ligne. et avec g sur toute la ligne..
bref on pourrait faire
sed "s/foo/bar/" monfichier
c'est plus propre et meme rajouter -i pour éditer sur place et pas rediriger dans le stdout..
mais bon je te laisse lire le man..
Faut mieux me lire yanimal ;-)
Hors ligne
oula je suis vraiment confus je sais pas ce qui m'est passe par la tête car jusqu a maintenant en plus j'utilisais bien le sed de cette facon .... mdr
Hors ligne
rectification il manque probablement quelque chose dans l'algorythme car ca me fait la même chose sur le bureau lol
c est ce genre de noms qui deconne :
, Sélectionnez votre aller, Sélectionnez votre aller,
, The_Edinburgh_Journal_of_Science.pdf, The_Edinburgh_Journal_of_Science.pdf,
, Histoire birefringence.doc, Histoire birefringence.doc,
, Modalitéspratiques[1].pdf, Modalitéspratiques[1].pdf,
, CV_COUZON.pdf, CV_COUZON.pdf,
, XLAB.EDEMA_02, XLAB.EDEMA_02,
etc...........
Hors ligne
ok problème trouvé..... mais je sais pas comment je vais m en depatouiller.....
si j applique l'algo sur mon fichier cible ca ne marche pas .......... si maintenant je fais une copie a la volée à savoir selectionner tout , que je le colle dans un fichier vierge et que j applique l algo sur ce nouveau fichier tout marche.......
il semble y avoir un probleme d'espacement quelques part ou je ne sais quoi..... je suis perdu la ^^
ou alors peut être un problème de mise en mémoire je sais pas trop....
ps : quand j applique sur le fichier cibre originale j'ai une breve apparition d'un fichier sur le bureau nomme "sedXXXXXX" comme un fichier temporaire qui disparait aussitot ce qui n'est pas le cas avec le second fichier
Dernière modification par yanimal (23 May 2008 11:44:52)
Hors ligne
ce que t'as donné BOFH ca ne va pas?
Et si tu ouvres le fichier original avec VI, y a des trucs louche ou il est parfaitement lisible?
Hors ligne
j'ai comparer avec un hexa decimal tout semble correcte : les 2 fichiers sont a l'identiques
j ai bien fait comme BOHF disais mais ca n'a rien change au probleme
mon sed n est plus en boucle c'est devenu une ligne banale
ah ok VI : bah j ai rien repere de suspect mafois si tu penses pouvoir avoir plus d infos je suis pret a t envoyer les 2 fichiers et ce fameux script
Dernière modification par yanimal (23 May 2008 15:43:54)
Hors ligne