Contenu | Rechercher | Menus

Annonce

Ubuntu 16.04 LTS
Commandez vos DVD et clés USB Ubuntu-fr !

Pour en savoir un peu plus sur l'équipe du forum.

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

#1 Le 11/09/2017, à 12:04

kholo

[tuto bash] changement valeurs dans un fichier texte

Bonjour à tous,
aujourd'hui on va modifier des fichiers de texte.
Le but est d'avoir une fonction facilement modifiable pour tester et changer une valeur sur une ligne dans le fichier du type

texte=une valeur

cas 1 simple
un fichier sert de référence à un interrupteur
je crée 2 fichiers
fichier 1 "on-off.txt"

on-off=0

fichier 2 "on-off.sh"

#!/bin/bash
# ----------------------------------------------
nomlogiciel="${0##*/}"
FONCTION="changement valeur dans un fichier texte - cas simple"
VERSION="alpha"
# NOTES DE VERSIONS
# ----------------------------------------------
# 
# ----------------------------------------------
echo "lancement $nomlogiciel..."

echo "------------------------
fichier avant modification"
#cat "on-off.txt"
echo $( < "on-off.txt") # autre façon de faire un cat

# modification de la valeur
#case $(cat "on-off.txt") in # UUOC mauvaise utilisation de cat
case $(< "on-off.txt") in
	on-off=1) echo "on-off=0" > "on-off.txt" ;;
	on-off=0) echo "on-off=1" > "on-off.txt" ;;
esac

echo "fichier après modification"
cat "on-off.txt"

exit 0

explications :
chaque fois que le script est lancé, il regarde dans le fichier et inverse la valeur en modifiant toute la ligne (et tout le fichier). on peut facilement récupérer la valeur avec un cat.
NB on peut faire plus simple et ne mettre dans le fichier que la valeur 0 ou 1 (mais j'ai pris cette forme pour la suite du tuto)

autre méthode simple

#!/bin/bash
# ----------------------------------------------
nomlogiciel="${0##*/}"
FONCTION="changement valeur dans un fichier texte - cas simple"
VERSION="alpha"
# NOTES DE VERSIONS
# ----------------------------------------------
# 
# ----------------------------------------------
echo "lancement $nomlogiciel..."
echo "------------------------
fichier avant modification"
read -r onOff <"on-off.txt"
echo "$onOff"
case $onOff in
	on-off=1) echo "on-off=0" > "on-off.txt" ;;
	on-off=0) echo "on-off=1" > "on-off.txt" ;;
esac
echo "fichier après modification"
# cat on-off.txt
echo "$( < on-off.txt)" # fait la même chose.

exit 0
Anonyme68 (expliqué) a écrit :
sed -i '/^on-off/y/01/10/' "on-off.txt"

ne marche que si la valeur contient qu'un chiffre

explication a écrit :

vous pouvez remplacer

case $onOff in
	on-off=1) echo "on-off=0" > "on-off.txt" ;;
	on-off=0) echo "on-off=1" > "on-off.txt" ;;
esac

par cette ligne

cas 2 : utiliser sed
fichier 1 "on-off.txt"

on-off=0
enabled=0
unTexte=gnouf gnouf
laVariable=et un autre

fichier 2 "on-off.sh"

#!/bin/bash
# ----------------------------------------------
nomlogiciel="${0##*/}"
FONCTION="changement valeur dans un fichier texte - cas 2 : utiliser sed"
VERSION="alpha"
# NOTES DE VERSIONS
# ----------------------------------------------
# 
# ----------------------------------------------
echo "lancement $nomlogiciel..."

dans1prendre2remplacer3par4 () {
	local unFichier="$1"
	local uneVariable="$2"
	local unTexte="$3"
	local unAutreTexte="$4"
	# echo "
	# unFichier=$unFichier
	# uneVariable=$uneVariable
	# unTexte=$unTexte
	# unAutreTexte=$unAutreTexte
	# "
	
	sed -i "s/${uneVariable}=${unTexte}/${uneVariable}=${unAutreTexte}/" "${unFichier}"
	}

echo "--------------------------------"
echo "fichier avant modification"
cat "on-off.txt"
dans1prendre2remplacer3par4 "on-off.txt" "laVariable" "et un autre" "avec du texte"
echo "--------------------------------"
echo "fichier après modification"
cat "on-off.txt"

exit 0

explications :
chaque fois que le script est lancé, cette fois il ne modifie que la ligne concernée avec la valeur envoyée mais il faut connaître la valeur actuelle sur la ligne

cas 3 : utiliser sed sans connaître la valeur de la variable à modifier
fichier 1 "on-off.txt"

on-off=0
enabled=0
unTexte=gnouf gnouf
laVariable=et un autre

fichier 2 "on-off.sh"

#!/bin/bash
# ----------------------------------------------
nomlogiciel="${0##*/}"
FONCTION="changement valeur dans un fichier texte - cas 3 : utiliser sed sans connaître la valeur de la variable à modifier"
VERSION="alpha"
# NOTES DE VERSIONS
# ----------------------------------------------
# 
# ----------------------------------------------
echo "lancement $nomlogiciel..."

dans1prendre2remplacerLaValeurpar3 () {
	local unFichier="$1"
	local uneVariable="$2"
	local unAutreTexte="$3"
	local unTexte="$( grep "${uneVariable}=" "$unFichier" )"
	unTexte="${unTexte##*${uneVariable}=}"
	
	sed -i "s/${uneVariable}=${unTexte}/${uneVariable}=${unAutreTexte}/" "${unFichier}"
	
	}
# mettre ici la valeur changée
nouvelleValeur="ce que je veux"

echo "--------------------------------"
echo "fichier avant modification"
cat "on-off.txt"
dans1prendre2remplacerLaValeurpar3 "on-off.txt" "laVariable" "${nouvelleValeur}"
echo "--------------------------------"
echo "fichier après modification"
cat "on-off.txt"
exit 0

explications :
chaque fois que le script est lancé, il ne modifie que la ligne concernée avec la valeur envoyée mais sans avoir à connaître la valeur actuelle de la variable

NB : les limites :
si une variable est identifiée 2 fois (si une ligne est commentée) c'est la dernière ligne concernée qui est modifiée et l'autre ou les autres non
on peut aller un peu plus loin en ajoutant une boucle qui changera toutes les valeurs correspondantes sans tenir compte du fait que certaines des lignes soient en commentaires
pas terrible mais fonctionnel...

fichier 1 "on-off.txt"

on-off=0
enabled=0
unTexte=gnouf gnouf
laVariable=hop hop hop
#laVariable=tout doit disparaitre

fichier 2

#!/bin/bash
# ----------------------------------------------
nomlogiciel="${0##*/}"
FONCTION="changement valeur dans un fichier texte - les limites"
VERSION="alpha"
# NOTES DE VERSIONS
# ----------------------------------------------
# 
# ----------------------------------------------
echo "lancement $nomlogiciel..."

dans1prendre2remplacerLaValeurpar3 () {
	local unFichier="$1"
	local uneVariable="$2"
	local unAutreTexte="$3"
	local unTexte="$( grep "${uneVariable}=" "$unFichier" )"
	IFS=$'\n' unTexte=( $unTexte )
	
	for leTexte in ${unTexte[@]}
	do
		leTexte="${leTexte##*${uneVariable}=}"
		sed -i "s/${uneVariable}=${leTexte}/${uneVariable}=${unAutreTexte}/" "${unFichier}"
	done
	}

# mettre ici la valeur changée
nouvelleValeur="ce que je veux"

echo "--------------------------------"
echo "fichier avant modification"
cat on-off.txt
dans1prendre2remplacerLaValeurpar3 "on-off.txt" "laVariable" "${nouvelleValeur}"
echo "--------------------------------"
echo "fichier après modification"
cat on-off.txt
exit 0

Dernière modification par kholo (Le 12/09/2017, à 10:07)

Hors ligne

#2 Le 11/09/2017, à 14:58

Watael

Re : [tuto bash] changement valeurs dans un fichier texte

salut,

cas 1 : UUOC

read -r onOff <on-off.txt
echo "$onOff"
case $onOff in
...
esac
cat on-off.txt # eh, oui ! il faut quand même afficher le résultat ;)
# mais ce n'est pas indispensable en bash :
echo "$( < on-off.txt)" # fait la même chose.

cas 3 : UUOC.
grep sait lire un fichier, comme sed, awk...


eval, c'est mal.

Hors ligne

#3 Le 11/09/2017, à 15:57

kholo

Re : [tuto bash] changement valeurs dans un fichier texte

merci Watael,
je vais essayer de retenir tout cela

la syntaxe

echo "$( < on-off.txt)"

est compliquée à retenir...
mais je comprends parfaitement l’intérêt de virer le cat et le pipe

Hors ligne

#4 Le 11/09/2017, à 20:59

Watael

Re : [tuto bash] changement valeurs dans un fichier texte

case $(echo $( < "on-off.txt")) in

bah, non.

case $(<on-off.txt) in

eval, c'est mal.

Hors ligne

#5 Le 12/09/2017, à 07:35

Anonyme68

Re : [tuto bash] changement valeurs dans un fichier texte

vous êtes fatigués ? big_smile

sed -i '/^on-off/y/01/10/' on-off.txt

ou c'est moi, enfin ça marche que si la valeur contient qu'un chiffre smile

UUOC c'est l'utilisation inutile de cat, si tu te retrouves avec une solution plus compliqué en évitant le cat, c'est plus un UUOC. UUOC != interdiction du cat

Dernière modification par Anonyme68 (Le 12/09/2017, à 07:42)


846/2381 jeux linux sur Steam

Vous avez plein d'ISO d'ubuntu ? Une bonne bande passante ? Aimer partager ? Essayer mon script

Hors ligne

#6 Le 12/09/2017, à 08:38

kholo

Re : [tuto bash] changement valeurs dans un fichier texte

ok,
j'en apprends tous les jours et plus j'en sais et plus j'en ai à apprendre...

je vais remettre les cat là où ils restent les plus évidents et j'en laisserai un pour l'exemple
je vais mettre la variante de Anonyme68 en avant avec les contre indications et l'alternative de Watael...
merci...
je suis aux anges !

Hors ligne

#7 Le 12/09/2017, à 12:18

kholo

Re : [tuto bash] changement valeurs dans un fichier texte

avec ce fichier je cherche à ne modifier que les lignes qui ne sont pas en commentaire

laVariable=de un
laVariable=deux deux # commentaire
# laVariable=de trois 
#laVariable=et cat

je cherche à tenir compte des lignes avec commentaires
mais ça reste "sale":

dans1prendre2remplacerLaValeurpar3 () {
	local unFichier="$1"
	local uneVariable="$2"
	local unAutreTexte="$3"
	local unTexte="$(grep "${uneVariable}=" "$unFichier")"
	IFS=$'\n' unTexte=( $unTexte )

Methode 1

	for leTexte in ${unTexte[@]}
	do
		leTexte="${leTexte##*${uneVariable}=}"
		sed -i "/^#/!s/${uneVariable}=${leTexte}/${uneVariable}=${unAutreTexte}/g" "${unFichier}"
		# attention ces lignes retirent les commentaires de fin de ligne
	done
	}

Methode 2

	for leTexte in ${unTexte[@]}
	do
		isCom=$( grep -E -v '^#' <<< ${leTexte} )
		if [ ${#isCom} -gt 1 ] ; then
			leTexte="${leTexte##*${uneVariable}=}"
			sed -i "s/${uneVariable}=${leTexte}/${uneVariable}=${unAutreTexte}/g" "${unFichier}"
			# attention ces lignes retirent les commentaires de fin de ligne
		# fi
	done
	}

sinon
-x sur le sed considère la ligne entière pour l'échange
mais ne tiendrait pas non plus compte des lignes avec des commentaires à la fin
donc on pourrait avoir tout ça...
des idées ?

Hors ligne

#8 Le 12/09/2017, à 13:47

Watael

Re : [tuto bash] changement valeurs dans un fichier texte

oulala, on s'y perd.

pourquoi utiliser et grep et sed et le remplacement de paramètres ?

soit un fichier de plusieurs lignes :

laVariable=de un
laVariable=deux deux # commentaire
# laVariable=de trois 
#laVariable=et cat

on veut, sur toutes les lignes qui ne sont pas commentées, remplacer toutes les expressions laVariable. <-un point, c'est tout.
voilà les spécifications, elles ne doivent plus changer pour l'exemple.
si on change les spécs, on change de cas.

d'abord, savoir lire un fichier en shell :

while read line; do echo "$line"; done < fichier

ensuite, on effectue la sélection : les lignes non commentées

 while read line; do test "${line:0:1}" = "#" && echo "remplace PAS -> $line" || echo "remplace -> $line"; done < fichier

si c'est bon, on fait le remplacement :

while read line; do test "${line:0:1}" = "#" || line="${line//laVariable/REMPLACÉ}"; echo "$line"; done < fichier

si on change les consignes, on change de cas.

Dernière modification par Watael (Le 12/09/2017, à 13:48)


eval, c'est mal.

Hors ligne

#9 Le 12/09/2017, à 14:21

kholo

Re : [tuto bash] changement valeurs dans un fichier texte

oui, c'est vrai je part un peu dans tous les sens...
au début je voulais juste un truc simple...
bon on y est...

maintenant un cas concret : la swappiness
par défaut, on a rien dans le fichier et ubuntu desktop swap avec une valeur de 60
pour modifier

echo vm.swappiness=5 | sudo tee /etc/sysctl.d/99-swappiness.conf

mais il peut arriver qu'on ai déjà mis une ligne avec la valeur... d'où ce fil,
mais aussi on peut avoir ajouté des lignes d'exemples ou de tests et se retrouver avec

#pour modifier le déclenchement de la swap utilisez "vm.swappiness=valeur"
#avec "valeur" en pourcentage avant déclenchement
#exemple 
#vm.swappiness=10
vm.swappiness=5

donc, je me suis dis qu'il suffisait de distinguer les lignes avec #
mais on peut avoir (on est d'accord les valeurs sont bidonnées)

#vm.swappiness=10 # pour un serveur
vm.swappiness=10 # pour ce que vous voulez

Hors ligne

#10 Le 12/09/2017, à 15:17

Watael

Re : [tuto bash] changement valeurs dans un fichier texte

fichier=/etc/sysctl.d/99-swapiness.conf
if test -s "$fichier"
then
    echo "le fichier existe et n'est pas vide"
# plusieurs traitements possibles :
#    si le fichier n'est pas gros : avec bash _seul_
#    si le fichier est gros : avec sed _seul_
#    s'il y a des calculs à effectuer : avec awk _seul_
elif test -f "$fichier"
then
    echo "le fichier est vide" #on peut l'écraser, avec une redirection.
else
    echo "le fichier n'existe pas" #il faut le créer, avec une redirection.
fi

Dernière modification par Watael (Le 12/09/2017, à 15:19)


eval, c'est mal.

Hors ligne

#11 Le 12/09/2017, à 17:37

Anonyme68

Re : [tuto bash] changement valeurs dans un fichier texte

$ cat fichier
laVariable=de un
laVariable=deux deux # commentaire
# laVariable=de trois 
#laVariable=et cat
$ sed -r 's/^[[:blank:]]*laVariable=[^#]*(#?.*)/laVariable=new value \1/' fichier 
laVariable=new value 
laVariable=new value # commentaire
# laVariable=de trois 
#laVariable=et cat

si j'ai bien suivi, un truc comme ça ?

$ cat fichier 
#pour modifier le déclenchement de la swap utilisez "vm.swappiness=valeur"
#avec "valeur" en pourcentage avant déclenchement
#exemple 
#vm.swappiness=10
vm.swappiness=5
$ sed -r 's/^[[:blank:]]*vm.swappiness=[^#]*(#?.*)/vm.swappiness=60 \1/' fichier
#pour modifier le déclenchement de la swap utilisez "vm.swappiness=valeur"
#avec "valeur" en pourcentage avant déclenchement
#exemple 
#vm.swappiness=10
vm.swappiness=60

PS : le ^[[:blank:]]* n'est pas obligatioire dans ce cas, mais si il y a un espace ou équivalent avant la variable

EDIT : simplification

Dernière modification par Anonyme68 (Le 12/09/2017, à 17:59)


846/2381 jeux linux sur Steam

Vous avez plein d'ISO d'ubuntu ? Une bonne bande passante ? Aimer partager ? Essayer mon script

Hors ligne