Bonjour.
Pourquoirenvoit-ilCode:echo 300 euros | sed "s/[0-9]*/$(( & - 2 ))/g"
au lieu de sortir "298 euros" ?Code:bash: & - 2 : erreur de syntaxe : opérande attendue (le symbole erroné est "& - 2 ")
Merci d'avance.
Version imprimable
Bonjour.
Pourquoirenvoit-ilCode:echo 300 euros | sed "s/[0-9]*/$(( & - 2 ))/g"
au lieu de sortir "298 euros" ?Code:bash: & - 2 : erreur de syntaxe : opérande attendue (le symbole erroné est "& - 2 ")
Merci d'avance.
Je ne suis pas le guru de sed et je comprends rien à ta commande.
Mais c'est la première fois que je vois quelqu'un essayer de faire des calculs avec sed.
D'habitude en shell, on utilise la built in command expr ou bc.
Exemple avec bc:Exemple avec expr:Code:
1
2
3 brouillons$ echo "300 - 2" | bc 298 brouillons$
Pour reproduire exactement l'affichage que tu recherches :Code:
1
2
3 brouillons$ echo 300 euros | expr $(awk '{print $1}') - 2 298 brouillons$
En espérant t'avoir aidé.Code:
1
2
3 brouillons$ echo 300 euros | awk '{print ($1 - 2) " " $2}' 298 euros brouillons$
wrong ! exprest une commande externe. :aie:Citation:
Envoyé par RaphaelIG
expr n'a déjà pas de sens dans un shell un peu moderne, mais expr| awk, c'est vraiment très moyen :(
ta dernière proposition est bien meilleure. :)
et, non, sed ne sait pas compter.
Edit : ah ! j'ai retrouvé : sed ne sait pas compter, mais
il peut exécuter des commandes :en général, dans des cas comme celui-là, je passe à awk, qui possède des capacités de calcul très importantes.Code:
1
2 echo 300 euros | sed 's/[0-9]*/echo $(( & - 2 ))/e' 298 euros
Bonjour,
Pour moi, l'execute du sed est buggé (voir le deuxième cas) :
Dans le cas donné, cela fonctionne, et donc si c'est un cas comme ça, on peut le faire en builtin:Code:
1
2
3
4 $ echo 300 euros | sed 's/[0-9]*/echo $(( & - 2 ))/e' 298 euros $ echo il y a 300 euros | sed 's/[0-9]*/echo $(( & - 2 ))/e' -2il y a 300 euros
Code:
1
2
3 $ XX="300 euros" $ echo $((${XX//[^0-9]/}-2))${XX//[0-9]} 298 euros
Oui, au temps pour moi, expr est bien une commande externe.
L'OP n'a pas précisé avec quel shell il travaille. Si il utilise du pur bourne shell (si si, ça existe encore sous Solaris par exemple) ou si il utilise le dash de Debian, les "$((compteur+1))" et "let compteur=compteur+1" ne fonctionnent pas.Citation:
expr n'a déjà pas de sens dans un shell un peu moderne, mais expr| awk, c'est vraiment très moyen :(
J'ai utilisé un awk, pour récupérer le 1er champ de sa commande echo. C'était juste pour illustrer l'usage d'expr qui a l'avantage de marcher partout (dash, bash, ... mais c'est normal, c'est une commande externe:mrgreen: ) au risque de paraître un peu old school.
Pourrais tu nous en dire plus ?Code:echo 300 euros | sed 's/[0-9]*/echo $(( & - 2 ))/e'
Comment sed sait que "echo $(( & - 2 ))" est une commande à exécuter plutôt qu'une expression rationnelle devant se substituer à "[0-9]*" ?
Que veut dire le "/e" à la fin ?
Citation:
Envoyé par RaphaelG
ah, bon.Code:
1
2
3 $ dash $ echo $(( 2 + 2 )) 4
Citation:
Envoyé par RaphaelG
Code:info sed 'Extended Commands'
Bonjour,
Je ne dirais pas que c'est buggé carCode:
1
2
3 $ echo il y a 300 euros | sed 's/[0-9]*/echo $(( & - 2 ))/e' -2il y a 300 euros
renvoie la phrase complète et pas uniquement les chiffres.Code:
1
2 echo il y a 300 euros | sed 's/[0-9]*/&/' il y a 300 euros
Comme ça, on obtient le résultat attendu.
Ici , on construit la commande dans le patern space.Code:
1
2 echo il y a 300 euros | sed 's/\(.* \)\([0-9]*\)\( .*\)/echo \1 $(( \2 - 2 )) \3/e' il y a 298 euros
Je n'arrive pas a trouver la syntaxe pour utilser cat fichier par exemple pour insérer fichier avant le patern space et remplacer la commande r qui va insérer fichier après le patern space
Si quelqu'un a une idée ?
Cordialement.
En fait, il n'est pas buggé et fait exactement ce qu'on lui demande. Seulement dans le deuxième cas la première position de la chaîne comptant entre zéro ou plusieurs chiffres est la chaîne vide au début de la chaîne. Pour éviter ça, il faudrait imposer au moins un chiffre:Code:
1
2 echo il y a 300 euros | sed 's/[0-9][0-9]*/echo $(( & - 2 ))/e' il y a 298 euros
En effet @disedorgue, la formule du typene fonctionne pas dans mon cas de figure (plus compiqué que ma simple demande avec 300 euros...Code:echo il y a 300 euros | sed 's/[0-9]*/echo $(( & - 2 ))/e'
Mais j'ai trouvé une solution grâce à @ctac_ et sa propositionJ'arrivais à obtenir ce que je voulais avec des variable, mais voulais réussir à le faire en une seule ligne, c'est chose faite. J'ai pu comparer les deux scripts (avec variables ou "en une ligne"), il mettent (sensiblement) le même temps à s’exécuter. Le but était de récupérer un chat Twitch et le convertir au format fichier ".srt" pour le joindre à la vidéo, ce qui prend, dans les deux cas, plus ou moins 2min30 pour une heure de vidéo (config pas très puissante).Code:echo il y a 300 euros | sed 's/\(.* \)\([0-9]*\)\( .*\)/echo \1 $(( \2 - 2 )) \3/e'
Je mets mes deux scripts dans les deux prochains posts (je ne mets pas de sortie vers un fichier dans ces exemples). J'ai mis le calcul du temps écoulé au sein du script, bien qu'on peut tout aussi bien l'obtenir avecCode:time Script.sh
Version "avec variables"
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 Vid=100035542 StartTime=`curl "https://rechat.twitch.tv/rechat-messages?start=1478717947&video_id=v$Vid" | sed "s/.*between \| and .*//g"` EndTime=`curl "https://rechat.twitch.tv/rechat-messages?start=1478717947&video_id=v$Vid" | sed "s/.* and \|\"}].*//g"` export StartTime=$StartTime Debut=`date` debut=`date +%s` echo $Debut echo "Récupération du chat..." | grep --color=auto ".*" echo "Durée de traitement estimée : 2'30'' par heure de vidéo" for var in `seq $StartTime 30 $EndTime` ; do Test=`wget -qO- "https://rechat.twitch.tv/rechat-messages?start=$var&video_id=v$Vid" | sed "s/\"type\"/\n/g" |grep -o "timestamp.*tags" |sed "s/.*/&::&/g" | sed "s/deleted\|from/DELETEHERE/" | sed "s/from/ENDHERE/" |sed "s/DELETEHERE.*ENDHERE/from/g" | sed "s/tags.*message/message/g" |sed "s/\",\"from.*//g" |sed "s/\",\"message\":\"/ : /g" | sed "s/timestamp\"://g" | sed "s/[0-9][0-9][0-9],\"/,&/g" | sed "s/ /--espace--/g"` for time in `echo $Test |sed "s/ /\n/g"|grep -o "^[0-9]*,[0-9]*"` ; do Milli=`echo $time | sed "s/.*,//g"` Full=`echo $time | sed "s/,$Milli//g"` Test=$(echo $Test | sed "s/$Full/`date -ud @\`echo $(( $Full - $StartTime ))\` +%H:%M:%S`,$Milli--espace---->--espace--`date -ud @\`echo $(( $Full - $(( $StartTime - 4 )) ))\` +%H:%M:%S`/g") done echo $Test | sed "s/ /\n/g" | sed "s/--espace--/ /g" done | grep -v "^$"|grep -n "^" | sed "s/,\"from\":\"/\n/g" |sed "s/^[0-9]*:/\n&\n/g" | sed "s/:$//g" echo "$Debut" date fin=`date +%s` date -ud @$(( $fin - $debut )) "+Durée de traitement : %H:%M:%S"
Version "en une ligne"
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 Vid=100035542 StartTime=`curl "https://rechat.twitch.tv/rechat-messages?start=1478717947&video_id=v$Vid" | sed "s/.*between \| and .*//g"` EndTime=`curl "https://rechat.twitch.tv/rechat-messages?start=1478717947&video_id=v$Vid" | sed "s/.* and \|\"}].*//g"` export StartTime=$StartTime Debut=`date` debut=`date +%s` echo $Debut echo "Récupération du chat..." | grep --color=auto ".*" echo "Durée de traitement estimée : 2'30'' par heure de vidéo" for var in `seq $StartTime 30 $EndTime` ; do wget -qO- "https://rechat.twitch.tv/rechat-messages?start=$var&video_id=v$Vid" | sed "s/\"type\"/\n/g" |grep -o "timestamp.*tags" |sed "s/.*/&::&/g" | sed "s/deleted\|from/DELETEHERE/" | sed "s/from/ENDHERE/" |sed "s/DELETEHERE.*ENDHERE/from/g" | sed "s/tags.*message/message/g" |sed "s/\",\"from.*//g" |sed "s/\",\"message\":\"/ : /g" | sed "s/timestamp\"://g" | sed "s/[0-9][0-9][0-9],\"/,&/g" | sed "s/ /--espace--/g"| sed "s/\"/,/g"| sed 's/\(^[0-9]*\)\(,[0-9]*\)\(.*\)/echo "$(date -d @$(( \1 - $StartTime )) +%H:%M:%S)\2--espace---->--espace--$(date -d @$(( $(( \1 - $StartTime )) +20 )) +%H:%M:%S)\2\3"/e' | sed "s/ /\n/g" | sed "s/--espace--/ /g" ; done | grep -v "^$"|grep -n "^" | sed "s/,,from,:,/\n/g" |sed "s/^[0-9]*:/\n&\n/g" | sed "s/:$//g" echo "$Debut" date fin=`date +%s` date -ud @$(( $fin - $debut )) "+Durée de traitement : %H:%M:%S"
Merci à tous pour votre aide en tout cas, je maitrise à présent mieux "sed" !
A priori, tu aimes perdre du temps pour lancer un sed par commande...
Qu'entends-tu par là (un sed par commande) ?
Exemple:
Ici, tu dois pouvoir remplacer tous les sed par un seul sed, comme par exemple via la syntaxe: sed -e "s/.*/&::&/g" -e "s/deleted\|from/DELETEHERE/" -e ..... parmi les syntaxes possibles...Code:sed "s/.*/&::&/g" | sed "s/deleted\|from/DELETEHERE/" | sed "s/from/ENDHERE/" |sed "s/DELETEHERE.*ENDHERE/from/g" | sed "s/tags.*message/message/g" |sed "s/\",\"from.*//g" |sed "s/\",\"message\":\"/ : /g" | sed "s/timestamp\"://g" | sed "s/[0-9][0-9][0-9],\"/,&/g" | sed "s/ /--espace--/g"| sed "s/\"/,/g"| sed 's/\(^[0-9]*\)\(,[0-9]*\)\(.*\)/echo "$(date -d @$(( \1 - $StartTime )) +%H:%M:%S)\2--espace---->--espace--$(date -d @$(( $(( \1 - $StartTime )) +20 )) +%H:%M:%S)\2\3"/e' | sed "s/ /\n/g" | sed "s/--espace--/ /g"
Sans doute oui, je n'y avais pas pensé et j'ai pris l'habitude d'enchainer les "sed" au fur et à mesure pour tester chaque étape, mais c'est tout aussi possible avec cet méthode.
Merci !
En fait cette option e ne fait pas ce à quoi on pourrait s'attendre (ce qui se passe pour les autres langages), c'est à dire que la commande echo $((&-2)) n'est pas interprétée au moment du remplacement qui est un simple remplacement, par contre, une fois le ou les remplacements effectués, c'est l'ensemble du pattern space qui est interprété.