Sed et retour à la ligne

Résolu/Fermé
radgeur Messages postés 201 Date d'inscription samedi 25 septembre 2010 Statut Membre Dernière intervention 20 juin 2012 - 19 juin 2012 à 12:03
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 - 20 juin 2012 à 10:43
Bonjour,

Voilà je cherche à remplacer des chaînes de caractères dans des dossiers et sous-dossiers sous Linux mais j'ai des problèmes lorsque des retours à la lignes viennent s'imiter dans la ligne que j'essaye de remplacer.

J'ai donc tout d'abord essayer avec la commande suivante :
#find /var/www -type f -exec sed -i -e 's/\($[a-z0-9A-Z_]*\)\( *= *\)\(reqmysql *(.*) *;\)/\1\2\3\n\1->execute();/g' {} \;
mais malheureusement comme expliquer au dessus, dès qu'il y a un retour à la ligne, ma commande ne s'exécute plus, sinon elle fonctionne parfaitement.

J'ai donc essaye ensuite avec une autre commande :
find /var/www -type f -exec sed -i -e 'N;s/\($[a-z0-9A-Z_]*\)\( *= *\)\(reqmysql *(\n*.*) *;\)/\1\2\3\n\1->execute();/g;P;D;' {} \;
Cette fois-ci les retours à la ligne sont bien prit en compte mais là encore un problème survient, je ne sais pas pourquoi, mais la ligne que j'essaye de rajouter avec ma commande s'écrit parfois plusieurs fois.


Si quelqu'un aurait une solution ou connaîtrais la raison de ce problème, je l'en remercie d'avance de bien vouloir m'en faire part.


4 réponses

zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
19 juin 2012 à 16:24
Re-

$ cat plop 
$req_joueurs= reqmysql('SELECT * FROM 'joueurs_internationaux' ORDER BY nom');

$req_param = reqmysql('
SELECT * FROM 'droit' JOIN 'table'
SELECT * FROM 'droit' JOIN 'table'
WHERE 'module'="livredor" AND 'page'="signer";
') ;

$ cat script.sed 
#n
:z
/^$/{
p
b
}
/) *;$/ {
s/\($[^ ]*[^=]*\)\( *=[^)]*) *;\)$/\1\2\n\1->execute();/
    p
    b
}
/) *;$/ !{
    N
    b z
    p
}

$ sed -f script.sed plop 
$req_joueurs= reqmysql('SELECT * FROM 'joueurs_internationaux' ORDER BY nom');
$req_joueurs->execute();

$req_param = reqmysql('
SELECT * FROM 'droit' JOIN 'table'
SELECT * FROM 'droit' JOIN 'table'
WHERE 'module'="livredor" AND 'page'="signer";
') ;
$req_param ->execute();

$ 

;-))
1
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
19 juin 2012 à 13:48
Salut,

Sed ne travaille que sur un flux contenu dans sa mémoire principale. En règle générale ce flux ne correspond qu'à une seule ligne d'un fichier. Pour que sed travaille sur un ensemble de lignes il faut concaténer ses lignes dans sa mémoire principale, et à partir de là la reconnaissance des fins de ligne peut être ciblée.

Il nous faudrait avoir des exemples précis et concrets des différents cas présents dans tes fichiers pour qu'on puisse t'aider ;-\
0
radgeur Messages postés 201 Date d'inscription samedi 25 septembre 2010 Statut Membre Dernière intervention 20 juin 2012 27
19 juin 2012 à 14:55
Dans les fichiers que j'ai a changer je peux tomber sur 2 cas distincts a remplacer :
Tout d'abord le premier, plus simple et plus courant :
$req_joueurs = reqmysql('SELECT * FROM 'joueurs_internationaux' ORDER BY nom');

Là, la première commande que j'ai créer fonctionne parfaitement et effectue bien ce que je souhaite.

Ensuite le deuxième que je peux rencontrer est le suivant :
$req_param = reqmysql('
SELECT * FROM 'droit' JOIN 'table'
SELECT * FROM 'droit' JOIN 'table'
WHERE 'module'="livredor" AND 'page'="signer";
') ;

et c'est celui là qui me pose problème, car je n'arrive pas à gérer convenablement les retours à la ligne, une action est bien effectuer, mais parfois effectuer plusieurs fois, je ne sais pourquoi et j'arrive donc parfois à la chose suivante:
$req_param = reqmysql('
SELECT * FROM 'droit' JOIN 'table'
SELECT * FROM 'droit' JOIN 'table'
WHERE 'module'="livredor" AND 'page'="signer";
') ;
$req_param->execute();
$req_param->execute();
$req_param->execute();

Alors que je souhaiterais que la ligne d'execute() ne soit écrite qu'une seule fois.
0
radgeur Messages postés 201 Date d'inscription samedi 25 septembre 2010 Statut Membre Dernière intervention 20 juin 2012 27
19 juin 2012 à 16:31
Re-,

Merci bien pour ta réponse, apparemment tu as trouver comment faire toi, mais ce serais possible d'avoir un peu de texte(explication), parce que là tu me balance du code brute et je ne saurais dire quoi correspond à quoi.

Merci d'avance.
0
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
Modifié par zipe31 le 19/06/2012 à 17:15
#n
Affichage sur commande uniquement

:z
On pose une étiquette

/^$/{
Motif correspondant à une ligne vide avec regroupement de commande entre les accolades

p
On imprime

b
Et on se branche à la fin du script, autrement dit le reste des commandes ne sera pas évalué pour ce motif

}
Fin du regroupement de commandes

/) *;$/ {
Motif correspondant à une fin de ligne (le $ en fin) finissant par une parenthèse fermante suivie ou pas d'un espace suivi d'un point virgule.

s/\($[^ ]*[^=]*\)\( *=[^)]*) *;\)$/\1\2\n\1->execute();/
Les substitutions avec référence-arrière. J'ai juste modifié leur nombre et la façon de matcher les motifs.

\($[^ ]*[^=]*\)
On matche tout jusqu'à ce qu'on rencontre un espace ou un signe égale. Le "[^=]" exclue le signe égale de la recherche.

\( *=[^)]*) *;\)$
Idem avec la parenthèse fermante. On cherche un motif commençant ou pas par un espace suivi du signe égale jusqu'à ce qu'on rencontre une parenthèse fermante, qu'on capture en l'incluant dans la référence-arrière. Le "$" à la fin signifie qu'on cherche une fin de ligne.

p
Si correspondance il y a c'est affiché

b
Et on se branche à la fin du script

}
Fin du regroupement de commandes

/) *;$/ !{
Si la ligne ne correspond pas (! indique la négation) au motif

N
On ajoute la ligne suivante

b z
Et on se branche à l'étiquette pour boucler (le "p" était en trop dans mon exemple ;-( )

}
Fin du regroupement de commandes



Apparemment l'affichage sur commande ne doit pas être top pour ton cas ;-(

Donc, tu peux réduire le script à :

:z
/^.*) *;$/ {
s/\($[^ ]*[^=]*\)\( *=[^)]*) *;\)$/\1\2\n\1->execute();/
    b
}
/) *;$/ !{
    N
    b z
}
0
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
19 juin 2012 à 19:24
Un zeste plus optimisé...

:z
/^\n*$.*) *;$/ {
s/\($[^ ]*[^=]*\)\( *=[^)]*) *;\)$/\1\2\n\1->execute();/
    b
}
/) *;$/ !{
    N
    b z
}
0
radgeur Messages postés 201 Date d'inscription samedi 25 septembre 2010 Statut Membre Dernière intervention 20 juin 2012 27
20 juin 2012 à 10:36
Merci beaucoup, ton code fonctionne effectivement parfaitement, ne me reste plus qu'à le comprendre pour pouvoir le modifier si besoin est.
0
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
20 juin 2012 à 10:43
Les explications sont ;-))

Voir aussi dans la FAQ : sed
0