Próbuję zmienić pojedyncze słowo w określonym wierszu w pliku, ale mam problemy z połączeniem wszystkich razem.
Zasadniczo w jednym wierszu w moim pliku znajduje się słowo kluczowe „wersja_oprogramowania”, a w tym wierszu (i tylko w tym wierszu) chcę zastąpić słowo „test” słowem „produkcja”.
Więc mogę to zrobić:
grep 'firmware_revision' myfile.py | sed 's/test/production'
Spowoduje to wybranie żądanej linii i wykonanie podstawienia, ale nie mogę wymyślić, jak przenieść tę nową linię do oryginalnego pliku, aby zastąpić starą. Oczywiście nie mogę po prostu przekierować go z powrotem do pliku, więc co powinienem zrobić?
Nawet jeśli używam grep
plików tymczasowych, używając tylko potrzebnego wiersza, tracę wszystkie inne dane w pliku, więc nie mogę już przekierować ich wszystkich do pliku tymczasowego, a następnie zastąpić oryginał tempem.
Edytuj - ktoś poprosił o więcej informacji
Powiedzmy, że mam plik pełen takich linii
[
('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')
]
teraz chcę napisać skrypt (najlepiej jednowierszowy), który znajdzie wiersz zawierający „wersja_sprawdzania oprogramowania” i zmieni wszystkie wystąpienia słowa „test” w tym wierszu na „produkcja”. Słowo „test” może znajdować się w innych miejscach tego pliku i nie chcę ich zmieniać. Żeby było jasne, chcę zmienić powyższą linię na
('firmware_revision', str, 'my-firmware-name-production', 'Firmware revision name')
Jak mam to zrobic?
źródło
sed
jest bardzo potężny, może wykonywać obie funkcje (grep
i podstawianie), ale potrzebujemy więcej informacji o tym, jak wygląda linia, aby ci pomóc.sed -i.bak '/firmware_revision/ s/test/production/' myfile.py
Odpowiedzi:
Próbować:
Tutaj
/firmware_revision/
działa jako warunek. Dotyczy to wierszy pasujących do wyrażenia regularnegofirmware_revision
i fałszem dla innych wierszy. Jeśli warunek jest spełniony, następuje wykonanie następującego polecenia. W tym przypadku, że rozkaz jest rozkazem substytut, który zastępuje pierwsze wystąpienietest
zproduction
.Innymi słowy, polecenie
s/test/production/
jest wykonywane tylko na liniach, które pasują do wyrażenia regularnegofirmware_revision
. Wszystkie pozostałe linie przechodzą bez zmian.Domyślnie sed wysyła dane wyjściowe do standardowego wyjścia. Chciałeś jednak zmienić plik na miejscu. Więc dodaliśmy
-i
opcję. W szczególności-i.bak
powoduje zmianę pliku w kopii zapasowej zapisanej z.bak
rozszerzeniem.Jeśli zdecydowałeś, że polecenie działa dla Ciebie i chcesz żyć niebezpiecznie i nie tworzyć kopii zapasowej, to w GNU sed (Linux) użyj:
Natomiast w BSD (OSX)
-i
opcja musi mieć argument. Jeśli nie chcesz przechowywać kopii zapasowej, podaj pusty argument. Dlatego użyj:Edytować
W edycji pytania PO żąda zastąpienia każdego wystąpienia
test
wierszaproduction
. W takim przypadku dodajemyg
opcję do polecenia zastępowania w celu zastąpienia globalnego (dla tej linii):źródło
-i.bak
część.-i
dodanego.sed
mogą zrobić ...''
po-i
?sed -i '/firmware_revision/ s/test/production/g' myfile.py
w przeciwnym razie zmieni się tylko pierwsza instancja.Na starszych komputerach ze starą szkołą,
sed
które nie obsługują opcji-i
:źródło
ed
i zrobić to w jednym wierszu:printf %s\\n g/firmware_revision/s/test/production/g w q | ed -s myfile.py
ed(1)
nie oferuje żadnego pretekstu do pokazania użyciamktemp(1)
.ed
robi. Zamiast tegomv -f "$TF" myfile.pl
użyjcat "$TF" > myfile.pl && rm -f "$TF"
. BTW, dobrą praktyką jest używanie małych nazw zmiennych ($tf
zamiast$TF
), gwarantuje się, że nie będą kolidować z żadnymi wbudowanymi zmiennymi bash (prawdopodobnie także z innymi powłokami Bourne'a).cat "$TF" > myfile.pl
spróbuj tego:touch a b; chmod 0444 a; cat b >a
(BTW,sed -i
w takim przypadku też nie będzie działać). Lepiej pozwól użytkownikowi sobie z tym poradzić. Odp:rm -f "$TF"
nie potrzebne, patrztrap ... EXIT
. Re:$tf
zamiast$TF
: może; to kwestia stylu.umask
różni się od pierwotnych perms. Jeśli chodzi o wielkie litery, nie jest to tylko kwestia stylu - wiele osób, które popełniły błąd przy użyciu wielkich liter PATH lub RANDOM lub SHELL, czy cokolwiek innego dla własnych zmiennych, znalazło trudną drogę. (i tak, często sam używam wielkich liter. Wiem, że to źle, próbuję zerwać z nałogiem).