#1 Le 02/05/2011, à 17:58
- yourchenko
Substitution sed par retour de fonction.
Bonjour, ca fait un bout de temps que je cherche un solution à ce problème, j'ai bien cherché sur le forum mais rien de similaire.
L'objectif de ce script est de retrouver des dates écrites du style "22/04/11", de les parsers et de les substituées.
Dans un premier temps, je me suis dirigé vers la fonction sed et le script suivant :
#Fonction qui prend en paramètre la date trouvée par sed, et qui est
#supposé retourné une valeur lui correspondat
function parseDates(){
#Some process here with $1 (the pattern found)
echo "dateParsed-$1-"> log.txt
echo "newVal"
}
export -f parseDates
et la commande sed suivante :
myCatFile=`sed -n 's/[0-3][0-9]\/[0-1][0-2]\/[0-9][0-9]/ '$(parseDates)' &/p' datefile`
où le & est la chaine représentant la date retrouvée.
Ce que je cherche à faire est d'appeller la fonction parseDates (ce qui fonctionne) mais de lui passer en plus en argument la date que sed vient de trouver.
Dans mon fichier log.txt je n'obtient que le resultat suivant :
"dateParsed--"
Peut-être y a-t-il une autre solution.. Mais je trouvais celle-ci élégante.
Merci d'avance!
Hors ligne
#2 Le 02/05/2011, à 18:05
- sputnick
Re : Substitution sed par retour de fonction.
Koff,
pas bien clair l'histoire, je ne comprends pas ce que tu cherche à faire. parsers et de les substituer ok, mais substituer par quoi ? oO
En tout cas, parseDates n'est pas appellé avec un agrument, donc forcement $1 n'existe pas dans la function.
Sinan, en 2011 on préfère
$( )
que la forme deprecated
` `
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#3 Le 02/05/2011, à 18:10
- yourchenko
Re : Substitution sed par retour de fonction.
Sinan, en 2011 on préfère
$( )
que la forme deprecated
` `
tu veux dire utiliser la commande sed ainsi :
myCatFile=$(sed -n 's/[0-3][0-9]\/[0-1][0-2]\/[0-9][0-9]/ '$(parseDates)' &/p') datefile
La fonction de substitution n'est pas encore faite, ca sera le travail de la fonction parseDates. Ce que je cherche à faire c'est tout d'abord d'avoir accès au pattern trouvé de sed dans ma fonction parseDates.
Hors ligne
#4 Le 02/05/2011, à 18:21
- sputnick
Re : Substitution sed par retour de fonction.
parseDates $(grep -o "[0-3][0-9]/[0-1][0-2]/[0-9][0-9]" datefile)
Pour sed, tu peut mettre ce que tu veut comme delimiteur, pas besoin de protéger les /.
Ex :
sed 's!foo!bar!g' <FILE>
Pour la fonction, il y aura plusieurs arguments si il y a plusieurs lignes dans ton fichier de dates, donc :
parseDates(){
#Some process here with $@ (the patterns found)
for arg; do
echo "dateParsed-${arg}-" >> log.txt
echo "newVal"
done
}
Dernière modification par sputnick (Le 02/05/2011, à 18:27)
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#5 Le 02/05/2011, à 18:25
- yourchenko
Re : Substitution sed par retour de fonction.
ok ca marche merci du conseil !Je continue à travailler la dessus
Hors ligne
#6 Le 02/05/2011, à 18:26
- sputnick
Re : Substitution sed par retour de fonction.
edit de mon ancien message
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#7 Le 02/05/2011, à 18:40
- yourchenko
Re : Substitution sed par retour de fonction.
Je ne sais pas si cette méthode va fonctionner au final, je pensais que le sed allait me substituer directement dans le buffer de mon fichier par les valeurs parsées. hors là je n'ai plus que les valeurs trouvée sans la ligne qui précède. il doit surement y avoir une option dans sed
Hors ligne
#8 Le 03/05/2011, à 21:17
- yourchenko
Re : Substitution sed par retour de fonction.
J'ai presque finit. Voila ou j'en suis.
Du coté de la substitution je suis arrivé a quelque chose de ce type
for line in $(cat $myFile); do
#Some process on the line (like if there is a space end line)
line=`echo $line | sed -e 's#[ | ]*$##g'`
for dateFound in $(echo $line | egrep -o "[0123]?[1-9]/[01]?[0-9]/[0-9]{2}$"); do
#The buf tempLine
tempLine=""
#echo "Date trouvée : "$dateFound
dateParsed=$(figureIt $dateFound)
tempLine=`echo $line | sed "s#$dateFound#& $dateParsed#g"`
line=$tempLine
done;
echo $line
echo $line >> buffer
done
Le seul soucis que j'ai est dans le :
for line in $(cat $myFile); do
est qu'il ne conserve pas les lignes vides. J'ai fait :
IFS=$'\r'
et j'ai vérifié, le cat prend bien en compte les lignes vides.
Je ne sais pas comment guarder les lignes vides..
Ou de manière plus générale : comment faire pour que la syntaxe suivante garde les lignes vides de mon fichier myfile.
#avec
IFS=$'\r'
for line in $(cat $myfile); do
echo $line >> $myNewfile
done
une idée?
Hors ligne
#9 Le 03/05/2011, à 21:56
- Postmortem
Re : Substitution sed par retour de fonction.
Salut !
Plutôt que for, tu pourrais utiliser while :
while read
do
echo "$REPLY" >> $myNewfile
done < $myfile
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#10 Le 03/05/2011, à 22:04
- yourchenko
Re : Substitution sed par retour de fonction.
Je l'ai essayé aussi. Cependant j'ai des soucis il me manque parfois la fin du fichier pour une syntaxe équivalente.
Hors ligne
#11 Le 03/05/2011, à 22:21
- Postmortem
Re : Substitution sed par retour de fonction.
Ce n'est pas le "while read" qui mange la fin du fichier, tu dois le perdre autre part.
Il doit être perdu par ta deuxième boucle for. Si egrep -o "[0123]?[1-9]/[01]?[0-9]/[0-9]{2}$" te sort plus d'une date, tu ne mets que la dernière dans ton fichier buffer
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#12 Le 04/05/2011, à 00:49
- yourchenko
Re : Substitution sed par retour de fonction.
Ok merci! je test ça demain
Hors ligne
#13 Le 04/05/2011, à 01:01
- sputnick
Re : Substitution sed par retour de fonction.
Effectivement, pour lire un fichier ligne à ligne, on n'utilise while read.
Attention aux quotes, use more quotes ! http://wiki.bash-hackers.org/syntax/quoting
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#14 Le 04/05/2011, à 12:08
- yourchenko
Re : Substitution sed par retour de fonction.
Avec while read j'ai bien mes newline (meme un peu trop). Cependant, il me manque toujours la fin du fichier. Exemple :
while read
do
echo "$REPLY" >> buffer
done < myFile
avec le fichier suivant :
j'aime les patates 5/5/11
et les fruits 7/5/11
c'est tout
m'affiche :
>
>j'aime les patates 5/5/11
>
>et les fruits 7/5/11
>
Je ne comprends pas.
Dernière modification par yourchenko (Le 04/05/2011, à 12:08)
Hors ligne
#15 Le 04/05/2011, à 19:13
- pode
Re : Substitution sed par retour de fonction.
Il faut déclarer une variable après read.
Par exemple :
$ cat ./read.sh
#!/bin/bash
> fichier_duplique
while read ligne
do
echo "$ligne" >> fichier_duplique
done < fichier
qui permet de dupliquer exactement le contenu :
$ ./read.sh
$ diff -u fichier fichier_duplique
$
Hors ligne
#16 Le 04/05/2011, à 20:53
- Postmortem
Re : Substitution sed par retour de fonction.
Il faut déclarer une variable après read.
Non, pas forcément. Si on ne met pas de nom de variable, REPLY est utilisé. C'est une astuce que j'ai appris ici-même et tu la trouves dans le man :
REPLY Mis à la ligne de saisie lue par la commande interne read lorsqu'aucun argument n'a été fourni.
Ça permet aussi de garder la mise en forme, les espaces au début ou à la fin des lignes par exemple, alors qu'en précisant une variable, tu perds les espaces.
@yourchenko, j'ai essayé ton exemple et moi je récupère bien tout... Moi non plus pas comprendre !
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#17 Le 04/05/2011, à 22:25
- pode
Re : Substitution sed par retour de fonction.
pode a écrit :Il faut déclarer une variable après read.
Non, pas forcément. Si on ne met pas de nom de variable, REPLY est utilisé. C'est une astuce que j'ai appris ici-même et tu la trouves dans le
Pas mal...
Pour ce qui est de la dernière ligne bouffée, c'est peut-être un problème "classique" de fichier qui n'a pas de eol (end of line) sur la dernière ligne.
Voici une reproduction de ce problème avec un fichier sans eol (pour distinguer le prompt du shell du $ affiché par la commande cat -A, le prompt est noté pode:~$).
Étape 1 - Création d'un fichier sans eol sur la dernière ligne :
pode:~$ echo -en " premiere ligne \n derniere ligne sans eol" > fichier
pode:~$ cat -A fichier
premiere ligne $
derniere ligne sans eolpode:~$
(le prompt pode:~$ s'affiche juste après "sans eol")
Étape 2 - Script de duplication :
pode:~$ cat ./readreply.sh
#!/bin/bash
> fichier_duplique
while read
do
echo "$REPLY" >> fichier_duplique
done < fichier
Étape 3 - Vérification que le fichier dupliqué ne contient pas la dernière ligne :
pode:~$ cat -A fichier_duplique
premiere ligne $
Voici une astuce basée sur awk, pour rajouter un eol à la dernière ligne d'un fichier qui n'en a pas (et qui ne fait rien si le fichier a déjà un eol sur sa dernière ligne) :
pode:~$ awk ' { print $0 } ' fichier > fichier_avec_eol
pode:~$ cat -A fichier_avec_eol
premiere ligne $
derniere ligne sans eol$
Hors ligne
#18 Le 04/05/2011, à 23:49
- FRUiT
Re : Substitution sed par retour de fonction.
pode:~$ awk ' { print $0 } ' fichier > fichier_avec_eol
Intéressant comme technique, cela dit peut-être sera-t-il plus judicieux de modifier le fichier lui même plutôt que de créer un fichier temporaire. D'autre part $0 est implicite pour la fonction print en cas d'absence d'argument(s). Ce qui donne :
awk '{ print > FILENAME }' fichier
Et pour ce qui est de read et $REPLY, une petite précision tout de même ça ne marche QUE avec read bash, et non read sh... (ce qui est bien dommage)
Dernière modification par FRUiT (Le 05/05/2011, à 00:18)
Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean
Hors ligne
#19 Le 05/05/2011, à 16:07
- yourchenko
Re : Substitution sed par retour de fonction.
Ah ça fonctionne! le problème venait du faite que mon fichier était mal formé..
Merci beaucoup pour votre aide!
PS : je vais regarder comment substituer directement dans le fichier. Mon soucis était que c'est une substitution par retour de fonction. J'ai eu des soucis avec sed et finalement je me suis résigné à lire le fichier ligne/ligne et de le stocker dans un buffer.
Merci encore
Edit : Un professeur ma donné une méthode en perl. Merci à Remi L.
perl -i -ape 'sub f {print "DATE: $_[0]\n"; return "xyz";} s|(\d\d/\d\d/\d\d\d\d)|f($1)|ge;' /tmp/toto
Dernière modification par yourchenko (Le 06/05/2011, à 11:47)
Hors ligne