J'essaie de remplacer une ligne dans le fichier et je rencontre des problèmes.
Fichier d'origine:
export PS1="\n\[\e[32;1m\][\[\e[37;1m\]\u@\h:\[\e[37;1m\]\w\[\e[32;1m\]]\\$ \[\e[0m\]"
Commande que j'exécute:
export PS1=" [e[32;1m][[e[37;1m]@h:[e[37;1m]w[e[32;1m]]\$ [e[0m]
Message d'erreur:
sed -i 's~PS1.*~PS1="\n\[\e[32;1m\][\[\e[37;1m\]\u@\h:\[\e[37;1m\]\w\[\e[32;1m\]]\\$ \[\e[0m\]~g' ~/.bashrc
J'ai aussi essayé sed:
syntax error at -e line 1, near "e[" Execution of -e aborted due to compilation errors.
Résultat avec Sed:
perl -pi -e 's~PS1.*~PS1="\n\[\e[32;1m\][\[\e[37;1m\]\u@\h:\[\e[37;1m\]\w\[\e[32;1m\]]\\$ \[\e[0m\]~g' ~/.bashrcFichier de résultat attendu:
export PS1='\h:\w\$ '
Résultat final
Cela n'a pas grand-chose à faire avec la question sauf à montrer aux gens à quoi ressemblera la PS1 lorsqu'elle fonctionnera correctement
3 Réponses :
Pour sed
, vous devez échapper chaque barre oblique inverse avec une autre barre oblique inverse pour qu'elles soient traitées littéralement.
La commande s
vous oblige également à échapper le délimiteur &
, il est donc plus facile d'utiliser la commande c
, de sorte que doubler les contre-obliques est la seule exigence:
hello export PS1="\n\[\e[32;1m\][\[\e[37;1m\]\u@\h:\[\e[37;1m\]\w\[\e[32;1m\]]\\$ \[\e[0m\]" world
Si file.txt
contient:
hello PS1=foo world
puis après avoir exécuté cette commande, il contiendra:
sed -i '/PS1/c\ export PS1="\\n\\[\\e[32;1m\\][\\[\\e[37;1m\\]\\u@\\h:\\[\\e[37;1m\\]\\w\\[\\e[32;1m\\]]\\\\$ \\[\\e[0m\\]" ' file.txt
Utilisez simplement un outil qui peut fonctionner avec des chaînes littérales, par exemple awk:
$ new='"\n\[\e[32;1m\][\[\e[37;1m\]\u@\h:\[\e[37;1m\]\w\[\e[32;1m\]]\\$ \[\e[0m\]"' \ awk 'sub(/PS1=.*/,"PS1="){$0=$0 ENVIRON["new"]} 1' file export PS1="\n\[\e[32;1m\][\[\e[37;1m\]\u@\h:\[\e[37;1m\]\w\[\e[32;1m\]]\\$ \[\e[0m\]"
ou si vous préférez:
$ awk 'BEGIN{new=ARGV[1]; ARGV[1]=""} sub(/PS1=.*/,"PS1="){$0=$0 new} 1' \ '"\n\[\e[32;1m\][\[\e[37;1m\]\u@\h:\[\e[37;1m\]\w\[\e[32;1m\]]\\$ \[\e[0m\]"' file export PS1="\n\[\e[32;1m\][\[\e[37;1m\]\u@\h:\[\e[37;1m\]\w\[\e[32;1m\]]\\$ \[\e[0m\]"
sed ne dispose d'aucun mécanisme pour comprendre les chaînes littérales, voir Est-il possible d'échapper de manière fiable aux métacaractères regex avec sed pour les cerceaux que vous devez franchir pour que sed agisse comme si c'était le cas.
Vous pouvez le faire en utilisant du code Bash pur avec:
newps1='"\n\[\e[32;1m\][\[\e[37;1m\]\u@\h:\[\e[37;1m\]\w\[\e[32;1m\]]\\$ \[\e[0m\]"' readarray -t bashrc_lines <~/.bashrc printf '%s\n' "${bashrc_lines[@]/PS1=*/PS1=$newps1}" >~/.bashrc
Le seul guillemet requis est de mettre des guillemets simples autour de la chaîne exacte (y compris les guillemets doubles) à mettre dans le à droite de PS1=
.
Le code nécessite Bash 4 (ou 5) pour readarray
. Il lit tout le fichier '.bashrc' en mémoire, mais cela ne devrait pas poser de problème en pratique. (S'il est trop gros pour être chargé en mémoire, il est certainement trop gros pour être un '.bashrc' utile.)
Voir Remplacement d'une partie d'une chaîne (BashFAQ / 100 (Comment faire une manipulation de chaîne dans bash?)) pour plus d'informations sur la façon dont la substitution est effectuée.
Merci d'inclure des instructions claires pour la reproduction, ainsi que les résultats attendus et réels! Vous devriez également prendre le temps d'essayer de réduire le problème. Par exemple, ce problème n'est pas spécifique à PS1, et un MCVE pourrait être "Pourquoi
echo" foobar "| sed 's / foo / \ n /'
génère un saut de ligne + barre au lieu de\ nbar
? " Voir Combien d'efforts de recherche sont attendus de Stack Overflow utilisateurs?