Vous n'êtes pas identifié(e).
Futur nouvel inscrit, tu dois au préalable lire l'intégralité des 10 articles des règles, s'il te plaît. Tout nouveau compte qui ne respecte pas les règles sera supprimé par l'administration.
Pages : 1
Hello les spécialistes des scripts, je pense notamment à ctesc356.
Comment est-il possible de traiter une ligne composée dans un script bash ?
Exemple avec un fichier de dates d'anniversaire :
12-04-1948 Christian Le Moigne
....
Je n'ai pas de problème avec la date pour en sortir un âge, mais c'est avec l'ensemble "nom prénom" qui comporte un blanc entre le nom et le prénom et avec le nom qui comporte également un blanc que j'ai des problèmes. Je voudrais que le résultat ressorte comme, par exemple :
Anniversaire aujourd'hui : Christian Le Moigne
Merci pour vos conseils.
Dernière modification par Clm76 (6/09/2020 19:16:12)
Fg 2020.4.0 - Linux Mint 21.3 Victoria - Cinnamon et Mate en dual boot - CM Asus P8H67 MLE - CPU i7 3770K - 12 Go Ram - Nvidia Geforce GTX 1660TI - Driver Nvidia 525
+ Hp notebook-15 - Linux Mint 21.3 Victoria - CPU i3-7020u - Ram 4Go - Intel Graphics 620.
Hors ligne
Bonjour,
Avec Bash, tu peux utiliser le built-in read:
#! /bin/bash
while read -r date nom; do
printf "Anniversaire aujourd'hui : %s\n" "$nom"
done
Ici, la lecture se fait depuis l'entrée standard, ce qui est pratique pour enchaîner les commandes au sein de pipelines :
./nom-du-script < fichier_de_données
ou
... | ./nom-du-script
mais tu peux lire depuis un fichier en ajoutant une redirection après le 'done' :
while read -r date nom; do
printf "Anniversaire aujourd'hui : %s\n" "$nom"
done < /chemin/vers/fichier/de/données # ou bien, p. ex. < "$1"
Ceci dit, si ton script n'est pas bourré d'appels de commandes, je conseillerais plutôt Python car la programmation en langages shell Bash & Co devient vite pénible dès qu'on veut faire des choses un chouilla plus compliquées ou générales. En lisant encore les données depuis l'entrée standard, on peut faire :
#! /usr/bin/env python3
import sys
for line in sys.stdin:
date, nom = [ champ.strip() for champ in line.split(' ', maxsplit=1) ]
print("Anniversaire aujourd'hui : {}".format(nom))
Ici, on enlève le \n de fin de ligne et d'éventuels espaces, tabulations, etc. au début et à la fin de chaque champ avant de le traiter (c'est le but du strip()).
Debian GNU/Linux, driver libre pour carte Radeon HD 4670, FG 'next', 8 Go de RAM
Hors ligne
J'aurais trouvé... mais beaucoup plus compliqué on reconnaît le maître...
je conseillerais plutôt Python
pareil, dans Python il existe moult fonctions et librairies pour triturer des chaînes dans tous les sens.
Intel i5-9400F, 16Go Ram, Nvidia GTX1660Ti, Linux Mint
Hors ligne
Salut,
je pense que sed serait ton ami ici
echo anniversaire(s) du jours: $(sed -n 's/^[0-9]* //p' < ton_fichier_avec_les_dates_et_noms)
On pourrait faire un truc un peu plus évolué pour mettre les données dans un tableau (nom+prénom dans chaque case) histoire de voir s'il y en a plus d'un et afficher l'anniversaire du jour que si il y en a et mettre anniversaire au pluriel si nécessaire:
declare -a anniv_du_jour
eval echo $(sed -rn 's/^[0-9-]* (.+)$/anniv_du_jour[${#anniv_du_jour[@]}="\1";/p' < ton_fichier_avec_les_dates_et_noms)
if test ${#anniv_du_jour[@]} -gt 0; then
print anniversaire
test ${#anniv_du_jour[@]} -gt 1 && print s
echo " du jour:"
for ((i=0; i<${#anniv_du_jour[@]}; i++)); do
echo ${anniv_du_jour[i]}
done
fi
pas testé, écrit à la volée, mais c'est l'idée
@+
bons vols
zakh
Dernière modification par zakharov (28/08/2020 14:11:24)
le zkv1000
Debian Bookworm sur i7-9750H, 16G, NV GeForce GTX 1660 Ti MaxQ 6Go
FG next compilé à la mano
Joystick TM T. Stick X avec fichier de conf perso
Hors ligne
on reconnaît le maître...
+ 1
Sûr que sur ce plan rominet c'est un bon.
Mais zakh pas mauvais du tout non plus.
Dans la passé, dans signature, il y avait un lien, "les scripts de zakh" !
Et il y en avait un paquet !
André. anciennement taureau89_9
Debian Testing Amd64. CM Sabertooth 990FX, FX8350, 32 Go Ram DDR3 1866 Mhz, GTX 1060 6Go, DD 2To Sata 3, THRUSTMASTER T.Flight StickX, FG 2020.4.0 Git.
Hors ligne
Dans la passé, dans signature, il y avait un lien, "les scripts de zakh" !
'Sont toujours là au moins en partie de qualité variable bien sûr.
D'ailleurs y en a un tout nouveau pour faire une bdd des appareils de FGaddons et suivre les maj avec un fgfs --update-fgaddon (pas fini y a un soucis avec les dates de dernière maj), et d'ailleurs le script qui gère fgfs permet de vérifier si la révision git de SG/FG passe la compile sur Jenkins de FG
@+
bons vols
zakh
le zkv1000
Debian Bookworm sur i7-9750H, 16G, NV GeForce GTX 1660 Ti MaxQ 6Go
FG next compilé à la mano
Joystick TM T. Stick X avec fichier de conf perso
Hors ligne
Waouh !!! Merci à tous, je vais étudier cela de plus près ... pour me détendre un peu du nasal et CX.
Je débute en bash et ne connais pas python mais je vais quand même y jeter un coup d’œil pour voir ce que ça dit. Merci encore
Fg 2020.4.0 - Linux Mint 21.3 Victoria - Cinnamon et Mate en dual boot - CM Asus P8H67 MLE - CPU i7 3770K - 12 Go Ram - Nvidia Geforce GTX 1660TI - Driver Nvidia 525
+ Hp notebook-15 - Linux Mint 21.3 Victoria - CPU i3-7020u - Ram 4Go - Intel Graphics 620.
Hors ligne
Oui, sauf que chez moi le premier des trois liens ne donne rien.
Chemin_de_seb.lautre.net_a_completer .
André. anciennement taureau89_9
Debian Testing Amd64. CM Sabertooth 990FX, FX8350, 32 Go Ram DDR3 1866 Mhz, GTX 1060 6Go, DD 2To Sata 3, THRUSTMASTER T.Flight StickX, FG 2020.4.0 Git.
Hors ligne
Bonjour à tous,
Je débute en bash et ne connais pas Python mais je vais quand même y jeter un coup d’œil pour voir ce que ça dit.
Finalement, j'ai écrit mon programme de rappel de dates d'anniversaire en Python (version 3). Il interroge un fichier .txt (Anniv.txt) dont les lignes sont de la forme :
jj-mm-aaaa:Prénom Nom
exemple : 12-04-1996:Ann Le Clem
Le programme est appelé à chaque démarrage de l'ordi et renvoie, pendant 20s une notification lorsque la ou les dates d'anniversaire sont dans les 8 jours.
Le programme :
#! /usr/bin/python3
# coding: utf-8
# Christian Le Moigne - sept 2020
import os,time
from datetime import date
annivFile=os.getenv('HOME')+'/Documents/Anniversaires/Anniv.txt'
today=time.strftime('%d-%m')
td=date.today()
msg=""
with open(annivFile,"r") as fichier:
for line in fichier:
line=line.split(':')
d1, m1, y1 = [int(x) for x in line[0].split('-')]
anniv=date(td.year, m1, d1)
diff=(anniv-td).days
age=td.year-y1
if today in line[0]:
msg+="Aujourd\'hui : "+line[1].rstrip()+" - "+str(age)+" ans \n\n"
if diff == 1:
msg+="Demain : "+line[1].rstrip()+" - "+str(age)+" ans \n\n"
if diff < 8 and diff > 1:
msg+="Dans "+str(diff)+" jours : "+line[1].rstrip()+" - "+str(age)+" ans \n\n"
if msg !="":
title="Anniversaires"
os.system('notify-send -t 20000 -i face-smile "'+title+'" "<b>'+msg+'</b>"')
msg=""
La notification :
Fg 2020.4.0 - Linux Mint 21.3 Victoria - Cinnamon et Mate en dual boot - CM Asus P8H67 MLE - CPU i7 3770K - 12 Go Ram - Nvidia Geforce GTX 1660TI - Driver Nvidia 525
+ Hp notebook-15 - Linux Mint 21.3 Victoria - CPU i3-7020u - Ram 4Go - Intel Graphics 620.
Hors ligne
On va finir par tout savoir sur la famille !
André. anciennement taureau89_9
Debian Testing Amd64. CM Sabertooth 990FX, FX8350, 32 Go Ram DDR3 1866 Mhz, GTX 1060 6Go, DD 2To Sata 3, THRUSTMASTER T.Flight StickX, FG 2020.4.0 Git.
Hors ligne
C'est pas mal, pour un début. Pour plus de lisibilité, je conseillerais de mettre un espace avant et après le = de l'affectation, +=, ==, + (en gros, les opérateurs binaires). En revanche, je n'en mets pas autour du = pour un argument nommé (comme le maxplit=1 de mon exemple). Et surtout, tu (Clm76) pourrais te débarasser d'os.system() au profit de fonctions du module subprocess. Exemple au tout début de la doc. :
>>> subprocess.run(["ls", "-l"]) # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)
Tu passes une liste d'arguments au lieu de passer une unique chaîne de caractères. Les listes sont hyper faciles à manipuler avec Python, donc c'est tranquille. Côté avantages :
- Ça ne lance pas un processus shell inutile ;
- Surtout, ça rend ton programme beaucoup plus robuste. En effet, comme une commande shell est une bête chaîne de caractères, il y a plein de caractères spéciaux : espace, \n, >, < &, |, ;, $, ", ', \... et cela pose problème si les arguments insérés dynamiquement dans ta commande contiennent certains d'entre eux. Il faut « échapper » les caractères spéciaux, mais c'est chiant (il y a cependant un module qui le fait : shlex) et totalement inutile. Avec l'autre approche, chaque argument de ta commande est un élément de la liste ; il est passé tel quel à l'appel système sous-jacent (tel qu'execvp() ou execvpe()), terminé. On peut aussi construire des pipelines sans passer par le shell (en faisant justement comme un shell).
Ici, pas de réel problème a priori, mais pour du code lancé avec des données non sûres (p. ex. exécuté comme script CGI pour un site Web, ou bien un progamme ayant accès à une ressource partagée et utilisé par tout un campus, etc.), l'utilisation de os.system() est extrêmement dangereuse (il est souvent très facile de fabriquer des arguments destinés à provoquer une exécution de code arbitraire grâce à $(...) ou quelque chose du genre).
J'ai mon script du même style qui regarde aussi /var/mail/$user, mais je n'utilise pas notify-send. J'utilise genmon pour la partie interface utilisateur (applet pour XFCE très personnalisable via scripting). C'est pas mal, mais sans doute moins visible ; il m'arrive de rater les anniversaires.
Debian GNU/Linux, driver libre pour carte Radeon HD 4670, FG 'next', 8 Go de RAM
Hors ligne
Et surtout, tu (Clm76) pourrais te débarasser d'os.system() au profit de fonctions du module subprocess.
Merci pour tes conseils. J'ai modifié en conséquence mon fichier.
J'ai aussi modifié le mode d'affichage (passage en critical) pour que la notification reste affichée jusqu'à sa fermeture manuelle, sinon elle disparaît au bout de 5 secondes.
A noter que, chez moi, notify-send -t 20000 par exemple (20 secondes d'affichage) ne fonctionne pas.
Le nouveau code :
#! /usr/bin/python3
# coding: utf-8
# Christian Le Moigne - sept 2020
import subprocess,datetime,time
from datetime import date
annivFile = '/home/chris/Documents/Anniversaires/Anniv.txt'
today = time.strftime('%d-%m')
td = date.today()
title = "Anniversaires"
msg = ""
with open(annivFile,"r") as file:
for line in file:
line = line.split(':')
d1, m1, y1 = [int(x) for x in line[0].split('-')]
anniv = date(td.year, m1, d1)
diff = (anniv-td).days
age = td.year-y1
if today in line[0]:
msg+="Aujourd\'hui : "+line[1].rstrip()+" - "+str(age)+" ans \n\n"
if diff == 1:
msg+="Demain : "+line[1].rstrip()+" - "+str(age)+" ans \n\n"
if diff < 8 and diff > 1:
msg+="Dans "+str(diff)+" jours : "+line[1].rstrip()+" - "+str(age)+" ans \n\n"
if msg != "":
subprocess.run(['notify-send','-u', 'critical', title, '<b>'+msg+'</b>'])
msg = ""
Fg 2020.4.0 - Linux Mint 21.3 Victoria - Cinnamon et Mate en dual boot - CM Asus P8H67 MLE - CPU i7 3770K - 12 Go Ram - Nvidia Geforce GTX 1660TI - Driver Nvidia 525
+ Hp notebook-15 - Linux Mint 21.3 Victoria - CPU i3-7020u - Ram 4Go - Intel Graphics 620.
Hors ligne
Pages : 1