J'essaie de changer un seul mot sur une ligne spécifique dans un fichier, mais j'ai du mal à me connecter tous ensemble.
Fondamentalement, sur une ligne de mon fichier, il y a un mot-clé 'firmware_revision', et sur cette ligne (et seulement cette ligne) je veux remplacer le mot 'test' par le mot 'production'.
Je peux donc faire ceci:
grep 'firmware_revision' myfile.py | sed 's/test/production'
Cela sélectionnera la ligne que je veux et effectuera la substitution, mais je ne peux pas comprendre comment obtenir cette nouvelle ligne dans le fichier d'origine pour remplacer l'ancienne ligne. Je ne peux évidemment pas simplement le rediriger vers le fichier, alors que dois-je faire?
Même si j'utilise grep
des fichiers temporaires, en utilisant pour obtenir uniquement la ligne dont j'ai besoin, je perds toutes les autres données du fichier, donc je ne peux plus simplement tout rediriger vers un fichier temporaire, puis remplacer l'original par le temp.
Modifier - Quelqu'un a demandé plus d'informations
Disons que j'ai un fichier plein de lignes comme ça
[
('key_name1', str, 'value1', 'Description'),
('key_name2', str, 'value2', 'Description'),
('key_name3', str, 'value3', 'Description'),
('firmware_revision', str, 'my-firmware-name-test', 'Firmware revision name')
]
maintenant, je veux écrire un script (idéalement une ligne) qui trouvera la ligne qui contient «firmware_revision» et change toutes les instances du mot «test» sur cette ligne en «production». Le mot «test» pourrait se trouver à d'autres endroits de ce fichier et je ne veux pas qu'ils soient modifiés. Donc, pour être clair, je veux changer la ligne ci-dessus en
('firmware_revision', str, 'my-firmware-name-production', 'Firmware revision name')
Comment puis-je faire cela?
la source
sed
est très puissant, il peut effectuer les deux fonctions (grep
et la substitution) mais nous aurons besoin de plus d'informations sur l'apparence de la ligne pour vous aider.sed -i.bak '/firmware_revision/ s/test/production/' myfile.py
Réponses:
Essayer:
Ici,
/firmware_revision/
agit comme une condition. C'est vrai pour les lignes qui correspondent à l'expression régulièrefirmware_revision
et faux pour les autres lignes. Si la condition est vraie, alors la commande qui suit est exécutée. Dans ce cas, cette commande est une commande de remplacement qui remplace la première occurrence detest
withproduction
.En d'autres termes, la commande
s/test/production/
n'est exécutée que sur les lignes qui correspondent à l'expression régulièrefirmware_revision
. Toutes les autres lignes passent inchangées.Par défaut, sed envoie sa sortie en sortie standard. Vous vouliez cependant modifier le fichier en place. Nous avons donc ajouté l'
-i
option. En particulier,-i.bak
entraîne la modification du fichier sur place avec une copie de sauvegarde enregistrée avec une.bak
extension.Si vous avez décidé que la commande fonctionne pour vous et que vous souhaitez vivre dangereusement et ne pas créer de sauvegarde, alors, avec GNU sed (Linux), utilisez:
En revanche, sur BSD (OSX), l'
-i
option doit avoir un argument. Si vous ne souhaitez pas conserver de sauvegarde, fournissez-lui un argument vide. Ainsi, utilisez:Éditer
Dans l'édition de la question, l'OP demande que chaque occurrence de
test
sur la ligne soit remplacée parproduction
. Dans ce cas, nous ajoutons l'g
option à la commande de remplacement pour un remplacement global (pour cette ligne):la source
-i.bak
partie.-i
ajout.sed
peuvent faire ...''
après-i
?sed -i '/firmware_revision/ s/test/production/g' myfile.py
sinon, seule la première instance est modifiée.Sur les machines plus anciennes avec la vieille école
sed
qui ne prend pas en charge l'option-i
:la source
ed
et le faire en une seule ligne:printf %s\\n g/firmware_revision/s/test/production/g w q | ed -s myfile.py
ed(1)
n'offre aucun prétexte pour montrer l'utilisation demktemp(1)
.ed
. Au lieu demv -f "$TF" myfile.pl
, utilisezcat "$TF" > myfile.pl && rm -f "$TF"
. BTW, il est recommandé d'utiliser des noms de variables en minuscules ($tf
au lieu de$TF
), ils sont garantis de ne pas entrer en conflit avec les vars intégrés de bash (probablement d'autres shells bourne aussi).cat "$TF" > myfile.pl
essayez ceci:touch a b; chmod 0444 a; cat b >a
(BTW,sed -i
ne fonctionnera pas dans ce cas non plus). Mieux vaut laisser l'utilisateur s'en occuper. Re::rm -f "$TF"
pas nécessaire, voyeztrap ... EXIT
. Re:$tf
au lieu de$TF
: peut-être; c'est une question de style.umask
diffère des perms d'origine. En ce qui concerne les vars en majuscules, ce n'est pas seulement une question de style - beaucoup de gens qui ont fait l'erreur d'utiliser des majuscules PATH ou RANDOM ou SHELL ou quoi que ce soit pour leurs propres variables ont trouvé la voie difficile. (et oui, j'utilise souvent des vars majuscules moi-même. Je sais que c'est faux, j'essaie de rompre avec l'habitude).