Je souhaite rechercher dans un fichier de configuration cette expression "central.database" . Je souhaite ensuite modifier le paramètre associé à "central.database" en "SQLTEST".
La disposition du fichier de configuration ressemblerait à ceci:
central.database = SQLFIRSTTEST
Voici ce que je veux qu'il ressemble après le remplacement de sed:
central.database = SQLTEST
Je le fais dans un script bash, toute suggestion, recommandation ou solution alternative est la bienvenue!
(En réalité, central.database
et SQLTEST
proviennent des variables bash ici.)
Mon code actuel (troisième tentative):
sshRetValue=$(ssh -p "35903" -i $HOME/sshids/idrsa-1.old ${1} <<EOF
sed -i "s/^\($CENTRAL_DB_NAME\s*=\s*\).*\$/\1$CENTRAL_DB_VALUE/" /home/testing.txt;
echo $?
EOF
)
Message d'erreur:
Pseudo-terminal will not be allocated because stdin is not a terminal.
sed: -e expression #1, char 58: unknown option to `s'
-bash: line 3: EOF: command not found
Voici un exemple d'expression:
sed -i 's/^\(central\.database\s*=\s*\).*$/\1SQLTEST/' file.cfg
Si vous voulez faire correspondre les éléments avec /
, vous pouvez utiliser un autre délimiteur:
sed -i 's#^\(cent/ral\.data/base\s*=\s*\).*$#\1SQL/TEST#' file.cfg
Ou avec expansion variable:
VAL="SQLTEST"
sed -i "s/^\(central\.database\s*=\s*\).*\$/\1$VAL/" file.cfg
Dans votre exemple:
sshRetValue=`sed -i "s/^\(\1$CENTRAL_DB_NAME\s*=\s*\).*\$/\1$CENTRAL_DB_VALUE/" /home/testing.txt`;
Il y a un\1 avant $ CENTRAL_DB_NAME qui n'est pas valide. De plus, sed n'imprime pas sa valeur de retour. C'est le moyen préféré pour vérifier les valeurs de retour:
sed -i "s/^\($CENTRAL_DB_NAME\s*=\s*\).*\$/\1$CENTRAL_DB_VALUE/" /home/testing.txt;
sed_return_value=$?
Et finalement, la tuyauterie vers SSH (non testée):
sed_return_value=$(ssh server <<EOF
sed -i "s/^\($CENTRAL_DB_NAME\s*=\s*\).*\$/\1$CENTRAL_DB_VALUE/" /home/testing.txt;
echo $?
EOF
)
Le -i sert à remplacer des données dans le fichier d'entrée. Sinon, sed écrit sur stdout.
Les expressions régulières sont un champ qui leur est propre. Il serait impossible de les expliquer en profondeur dans une réponse stackoverflow, à moins qu'une fonction spécifique ne vous échappe.
sed -i -e '/central.database =/ s/= .*/= new_value/' /path/to/file
Explication:
-i
indique à sed de sauvegarder les résultats dans le fichier d'entrée. Sans cela, sed imprimera les résultats sur la sortie standard./central.database =/
fait correspondre les lignes contenant la chaîne entre des barres obliques, c’est-à-dire "central.database =".s/OLD/NEW/
effectue une substitution. La chaîne OLD est une expression régulière à associer et la partie NEW
est la chaîne à remplacer..*
signifie "correspond à rien". Donc, = .*
correspond à un signe égal, à un espace, puis à tout le reste.Je sais qu'il est trop tard pour ajouter une réponse à cette question, cependant, j'ai pensé partager mes connaissances avec vous tous. J'ai suivi une approche très générale pour résoudre un problème similaire. J'ai supprimé la ligne entière qui correspond à la chaîne et ajouté les valeurs requises à cette clé. A votre question voici la réponse
replaceValue=SQLTEST
sed -i "/central.database =/d" /home/testing.txt
echo "central.database = $replaceValue" >> /home/testing.txt
sed supprime la chaîne correspondante du fichier et la ligne immédiatement suivante insère la clé et la valeur requises dans le fichier.
J'aime utiliser awk
pour cela, car il est assez facile de comprendre ce qu'il fait et prend très bien soin du séparateur (=
) et du fait qu'il doit être fait sur une ligne non commentée:
awk -v var="my_var" -v new_val="NEW VALUE" \ # set the vars
'BEGIN{FS=OFS="="} # set separator to =
match($1, "^\\s*" var "\\s*") { # check if it matches
$2=" " new_val # if so, replace the line
}1' conf_file # print all lines
Ceci utilise match()
pour vérifier si le motif se produit dans une ligne donnée. Si c'est le cas, il effectue le remplacement avec la valeur donnée.
Par exemple:
$ cat conf
hello
my_var= SOME VALUE
#my_var = ANOTHER VALUE
bye
Modifions la valeur dans my_var
en NEW VALUE
:
$ awk -v var="my_var" -v new_val="NEW VALUE" 'BEGIN{FS=OFS="="}match($1, "^\\s*" var "\\s*") {$2=" " new_val}1' conf
hello
my_var= NEW VALUE
#my_var = ANOTHER VALUE
bye
Il est également possible de définir les valeurs dans les variables Shell, puis de les utiliser avec -v
:
$ var="my_var"
$ new_value="NEW VALUE"
$ awk -v var="$var" -v new_val="$new_value" 'BEGIN{FS=OFS="="}match($1, "^\\s*" var "\\s*") {$2=" " new_val}1' conf
Et vous pouvez bien sûr mettre tout cela dans une fonction Shell que vous appelez ensuite normalement:
#!/bin/bash
replace () {
file=$1
var=$2
new_value=$3
awk -v var="$var" -v new_val="$new_value" 'BEGIN{FS=OFS="="}match($1, "^\\s*" var "\\s*") {$2=" " new_val}1' "$file"
}
# Call the replace() function with the necessary parameters
replace "conf" "my_var" "NEW VALUE"
Lors de l'exécution, cela retourne
hello
my_var= NEW VALUE
#my_var = ANOTHER VALUE
bye
Vous pouvez également faire en sorte que le script reçoive les paramètres de la manière suivante: ./script.sh "conf_file" "var_to_replace" "NEW VALUE"
pour les transmettre ensuite à la fonction.
Si vous souhaitez remplacer entre 2 fichiers de propriétés, vous pouvez utiliser ceci:
awk -F= 'NR==FNR{A[$1]=$2;next}$1 in A{$2=A[$1]}1' OFS='\=' /tmp/masterfile /opt/props/finalfile.properties > /tmp/tmp.txt && mv -f /tmp/tmp.txt /opt/props/finalfile.properties
J'ai utilisé ce script pour garder les priorités ..
Les arguments $ 1 aura un dossier dans lequel plusieurs fichiers de configuration existent. $ 2 aura des propriétés qui doivent être remplacées dans les fichiers chemin et sous-chemins $ 1 # 3 aura des propriétés qui doivent être écrasées sur $ 2
Il a également une logique cachée pour vérifier l'existence de variables d'environnement car les clés existent dans $ 2 et $ 3 et donnent la priorité à cela.
c'est-à-dire s'il existe une clé dans un environnement qui aurait la plus haute priorité. À côté de cela, 3 $ et à côté de cela, 1 $ de fichier.
#!/bin/bash
#Usage is propertyReplacer <CONFIG_FOLDER_PATH> <CONFIG_FILE_2ND_PRIORITY> <CONFIG_FILE_1ST_PRIORITY>
function propertyReplacer() {
filePathToAct="$1"
propertiesFilePath="$2"
propertiesSecureFilePath="$3"
declare -A keyValues
while IFS='=' read -r key value; do
if [ "$key" == "" ]; then
continue
Elif [[ "$key" =~ ^#.*$ ]]; then
continue
else
echo $key " --> " $value
keyValues[$key]=$value
fi
done < "$propertiesFilePath"
if [ ! -f "$propertiesSecureFilePath" ]; then
continue
else
while IFS='=' read -r key value; do
if [ "$key" == "" ]; then
continue
Elif [[ "$key" =~ ^#.*$ ]]; then
continue
else
echo $key " --> " $value
keyValues[$key]=$value
fi
done < "$propertiesSecureFilePath"
fi
for key in ${!keyValues[@]}; do
envProp=${key//[@]/}
if [ "$(eval echo '$'$envProp)" == "" ]; then
echo "Environment key not exist" $envProp
else
value=$(eval echo '$'$envProp)
echo "From Environment " $envProp " --> "$value
keyValues[$key]=$value
fi
done
find "$filePathToAct" | while read -r resultFileName; do
if [ ! -f "$resultFileName" ]; then
continue
else
echo "Acting on the file $resultFileName"
for key in ${!keyValues[@]}; do
value=$(echo "${keyValues[${key}]}" | sed 's/\//\\\//g')
echo "sed -i 's/$key/$value/g' $resultFileName "
eval "sed -i 's/$key/$value/g' $resultFileName "
done
fi
done
}