Extraction de champs par sed...

Fermé
leon91490 Messages postés 166 Date d'inscription mardi 19 mai 2009 Statut Membre Dernière intervention 9 septembre 2017 - Modifié le 9 sept. 2017 à 11:12
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 - 9 sept. 2017 à 16:25
Bonjour,

j'ai un souci pour extraire des champs via sed...

je recois un message d'erreur de exiftool

message d'erreur :
Error: 'essais/img-2017-09-08_20-34-25.NEF' already exists - _DSC2835.NEF


Mon but est d'avoir le fichier téléchargé en erreur (ici la destination existe dejà) et la destination... et ne pas ecraser la date du fichier voire les traitements effectués.
ensuite je lance la commande sed pour avoir les références arrieres. \1 et \2

\1 est le nom du fichier existant déjà avant le déplacement.
\2 est le fichier téléchargé dans Images.

la commande que je lance pour mettre au point:
$ echo "Error: 'essais/img-2017-09-08_20-34-25.NEF' already exists - _DSC2835.NEF" | sed  "s/^Error: \'\([a-zA-Z0-9_\.]+\)\' already exists - \([a-zA-Z\._]+\)$/\1#\2/"
Error: 'essais/img-2017-09-08_20-34-25.NEF' already exists - _DSC2835.NEF


je pense pas avoir oublié d'echapper les caracteres . ' et (

version de sed :


$ sed --version
sed (GNU sed) 4.2.2
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Jay Fenlason, Tom Lord, Ken Pizzini,
and Paolo Bonzini.
Page de GNU sed: <http://www.gnu.org/software/sed/>.
Aide générale pour utiliser les logiciels GNU: <http://www.gnu.org/help/gethelp.fr.html>.
Rapporter toutes anomalies à: <bug-sed@gnu.org>.
N'oubliez pas d'inclure le mot ``sed'' quelque-part dans la zone ``Subject:''.


merci d'avance de votre réponse. :)

A voir également:

3 réponses

zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
9 sept. 2017 à 11:44
Salut,

$ A="Error: 'essais/img-2017-09-08_20-34-25.NEF' already exists - _DSC2835.NEF"

$ echo "${A}" | sed "s#.*/\([^']*\).* \(.*\)#\1 = \2#"
img-2017-09-08_20-34-25.NEF = _DSC2835.NEF

C'est ça que tu veux ?
0
leon91490 Messages postés 166 Date d'inscription mardi 19 mai 2009 Statut Membre Dernière intervention 9 septembre 2017 47
Modifié le 9 sept. 2017 à 13:09
merci zipe31

merci ca marche votre commande.

mais j'aimerais comprendre la logique de ce sed et pourquoi ma commande ne marche pas.


chaque fois que j'ai une regexp à faire , je viens ici pour me faire aider. Ou est l'erreur dans ma commande. je comprends votre logique mais pour la comprendre et l'appliquer c'est pas pareil.
0
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
9 sept. 2017 à 13:17
Petite rectification pour commencer. J'ai oublié de cibler les lignes commençant par "Error" ;-((

Donc la syntaxe exacte serait plutôt :
sed "/^Error/ {s#.*/\([^']*\).* \(.*\)#\1 = \2#}"


s#regex#change#
Comme le motif recherchée contient un "/" (slash) séparateur par défaut de sed, il faut en changer. Ici j'ai mis un "#" (croisillon), mais tu peux mettre ce que tu veux à condition que le caractère ne soit pas dans la motif initial.

.*/
Comme apparemment les seuls slashs présents se trouvent avant le nom du fichier recherché, on joue sur la gourmandise des regex, notamment le quantificateur "*", et on cible tout ce qui se trouve avant le dernier slash dans le motif, donc on cible
Error: 'essais/
.

\([^']*\)
La 1ère référence arrière fait correspondre tous les caractères rencontrés à l'exception d'une apostrophe (ou simple quote), le
[^']
signifiant la négative.

.* 
On recherche ensuite tous les caractères jusqu'au dernier espace inclus. Note bien l'espace après l'étoile.

\(.*\)
Et enfin la 2nd référence arrière, fait correspondre toute la fin de la ligne qui contient le nom du fichier.

Petite précision : ici j'ai entouré l'expression avec des quotes doubles à cause de la quote simple que l'on recherche dans une des regex et qui pose souvent problème lorsqu'on doit les échapper.
Exemple :
$ echo "l'apostrophe" | sed 's/'\''/"/'
l"apostrophe

C'est assez imbuvable, non ? ;-))
0
leon91490 Messages postés 166 Date d'inscription mardi 19 mai 2009 Statut Membre Dernière intervention 9 septembre 2017 47
Modifié le 9 sept. 2017 à 15:10
je comprends pourquoi j'ai du mal avec les regexp.


je commence à comprendre. Depuis 1987 c'est un peu long


jai modifié votre commande pour inclure le dossier du fichier de destination. c'est pour afficher un log sur les erreurs... genre

fichier dscn1456.NEF : vers /media/dossier/de/classement/annee/mois/jour/ ERREUR, cible existante.

ensuite je vais mettre si tout se passe bien.

fichier dscn1897.NEF vers /media/dossier/de.../jour/ ok


Sinon je pense avoir compris comment faire. il faut trouver des séparateurs ou des moyens de reconnaitre les champs du reste du texte.

sinon je comprends pas comment sed fait lorsque vous mettez [^']*\).* \(etc

et derriere la quote simple il y a un espace et le .* devrait s'arreter à cet espace. .* espace ca veut dire que l'on s'arrete à l'espace et le message "allready exists a plusieurs espaces. Qu'est ce qui fait que sed s'arrete au dernier espace ?

logiquement si ca fait .* et espace ca s'arrete au premier espace. Et apparement il s'arrete au dernier espace. Mais selon quels criteres ?

et merci de vos conseils.
0
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
9 sept. 2017 à 16:25
logiquement si ca fait .* et espace ca s'arrete au premier espace.
Non, le quantificateur "*" est très gourmand, il englobe tout, jusqu'au dernier espace rencontré.

Pour s'arrêter au 1er espace on aurait mis
[^ ]*
et là il se serait arrêter au 1er espace rencontré.

On mange tout :
$ echo "a b c d e f" | sed 's/.* //'
f


On s'arrête avant le 1er espace :
$ echo "a b c d e f" | sed 's/[^ ]*//'
b c d e f


On s'arrête après le 1er espace :
$ echo "a b c d e f" | sed 's/[^ ]* //'
b c d e f
0