Ich versuche, ein einzelnes Wort in einer bestimmten Zeile in einer Datei zu ändern, habe jedoch Probleme, alle miteinander zu verbinden.
Grundsätzlich befindet sich in einer Zeile meiner Datei das Schlüsselwort 'firmware_revision', und in dieser Zeile (und nur in dieser Zeile) möchte ich das Wort 'test' durch das Wort 'Produktion' ersetzen.
Also kann ich das machen:
grep 'firmware_revision' myfile.py | sed 's/test/production'
Dadurch wird die gewünschte Zeile ausgewählt und die Ersetzung durchgeführt, aber ich kann nicht herausfinden, wie diese neue Zeile in die Originaldatei übernommen wird, um die alte Zeile zu ersetzen. Ich kann es natürlich nicht einfach zurück in die Datei umleiten. Was soll ich also tun?
Selbst wenn ich Provisorien verwende, grep
verliere ich alle anderen Daten in der Datei, indem ich nur die benötigte Zeile erhalte, sodass ich nicht mehr nur eine temporäre Datei in eine temporäre Datei umleiten und dann das Original durch die temporäre Datei ersetzen kann.
Bearbeiten - Jemand hat nach weiteren Informationen gefragt
Nehmen wir an, ich habe eine Datei voller solcher Zeilen
[
('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')
]
Jetzt möchte ich ein Skript (idealerweise ein Einzeiler) schreiben, das die Zeile mit 'firmware_revision' findet und alle Instanzen des Wortes 'test' in dieser Zeile in 'Produktion' ändert. Das Wort "Test" könnte sich an anderen Stellen in dieser Datei befinden, und ich möchte nicht, dass diese geändert werden. Um klar zu sein, möchte ich die obige Zeile in ändern
('firmware_revision', str, 'my-firmware-name-production', 'Firmware revision name')
Wie mache ich das?
quelle
sed
ist sehr leistungsfähig, kann beide Funktionen (grep
und Ersetzungen) ausführen, aber wir benötigen weitere Informationen darüber, wie die Zeile aussieht, um Ihnen zu helfen.sed -i.bak '/firmware_revision/ s/test/production/' myfile.py
Antworten:
Versuchen:
Hier
/firmware_revision/
wirkt als Bedingung. Dies gilt für Zeilen, die mit dem regulären Ausdruck übereinstimmen,firmware_revision
und für andere Zeilen. Wenn die Bedingung erfüllt ist, wird der folgende Befehl ausgeführt. In diesem Fall ist dieser Befehl ein Ersatzbefehl, der das erste Auftreten vontest
durch ersetztproduction
.Mit anderen Worten, der Befehl
s/test/production/
wird nur in Zeilen ausgeführt, die mit dem regulären Ausdruck übereinstimmenfirmware_revision
. Alle anderen Linien verlaufen unverändert.Standardmäßig sendet sed seine Ausgabe an den Standardausgang. Sie wollten jedoch die Datei an Ort und Stelle ändern. Also haben wir die
-i
Option hinzugefügt . Dies-i.bak
bewirkt insbesondere, dass die Datei mit einer Sicherungskopie geändert wird, die mit einer.bak
Erweiterung gespeichert wird .Wenn Sie entschieden haben, dass der Befehl für Sie funktioniert und Sie gefährlich leben und kein Backup erstellen möchten, verwenden Sie mit GNU sed (Linux):
Im Gegensatz dazu
-i
muss die Option unter BSD (OSX) ein Argument haben. Wenn Sie kein Backup erstellen möchten, geben Sie ein leeres Argument an. Verwenden Sie daher:Bearbeiten
Bei der Bearbeitung der Frage fordert das OP an, jedes Vorkommen
test
in der Zeile durch zu ersetzenproduction
. In diesem Fall fügen wirg
dem Ersatzbefehl die Option für eine globale (für diese Zeile) Ersetzung hinzu:quelle
-i.bak
Teil erläutern .-i
hinzugefügt.sed
was alles möglich ist ...''
nach-i
?sed -i '/firmware_revision/ s/test/production/g' myfile.py
Andernfalls wird nur die erste Instanz geändert.Auf älteren Maschinen mit Old-School
sed
, die keine Option unterstützen-i
:quelle
ed
und in einer Zeileprintf %s\\n g/firmware_revision/s/test/production/g w q | ed -s myfile.py
ed(1)
keinen Vorwand, um die Verwendung von zu zeigenmktemp(1)
.ed
.mv -f "$TF" myfile.pl
Verwenden Sie stattdessencat "$TF" > myfile.pl && rm -f "$TF"
. Übrigens ist es empfehlenswert, Variablennamen in Kleinbuchstaben zu verwenden ($tf
anstelle von$TF
). Sie stehen garantiert nicht in Konflikt mit integrierten Bash-Variablen (wahrscheinlich auch mit anderen Bourne-Shells).cat "$TF" > myfile.pl
versuche dies:touch a b; chmod 0444 a; cat b >a
(Übrigens,sed -i
funktioniert auch in diesem Fall nicht). Lassen Sie den Benutzer besser damit umgehen. Re ::rm -f "$TF"
nicht benötigt, siehetrap ... EXIT
. Re:$tf
statt$TF
: vielleicht; Es ist eine Frage des Stils.umask
von der ursprünglichen Dauerwelle abweicht. Bei Großbuchstaben ist es nicht nur eine Frage des Stils - viele Leute, die den Fehler gemacht haben, Großbuchstaben PATH oder RANDOM oder SHELL oder was auch immer für ihre eigenen Variablen zu verwenden, haben es auf die harte Tour herausgefunden. (und ja, ich benutze oft selbst Großbuchstaben. Ich weiß, dass es falsch ist, ich versuche, die Gewohnheit zu brechen).