Я пытаюсь изменить одно слово в определенной строке в файле, но у меня возникают проблемы с соединением всех вместе.
По сути, в одной строке моего файла есть ключевое слово «firmware_revision», а в этой строке (и только в этой строке) я хочу заменить слово «тест» словом «производство».
Так что я могу сделать это:
grep 'firmware_revision' myfile.py | sed 's/test/production'
Это выберет нужную мне строку и выполнит подстановку, но я не могу понять, как вставить эту новую строку в исходный файл, чтобы заменить старую строку. Я, очевидно, не могу просто перенаправить его обратно в файл, так что мне делать?
Даже если я использую временные grep
файлы, используя только нужную мне строку, я теряю все остальные данные в файле, поэтому я больше не могу просто перенаправить все это во временный файл, а затем заменить оригинал временным.
Изменить - Кто-то попросил дополнительную информацию
Допустим, у меня есть файл, полный строк, как это
[
('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')
]
Теперь я хочу написать скрипт (в идеале, однострочный), который найдет строку, содержащую «firmware_revision», и изменит все экземпляры слова «test» в этой строке на «production». Слово «тест» может быть в других местах в этом файле, и я не хочу, чтобы они были изменены. Чтобы было ясно, я хочу изменить приведенную выше строку на
('firmware_revision', str, 'my-firmware-name-production', 'Firmware revision name')
Как мне это сделать?
источник
sed
Он очень мощный, он может выполнять обе функции (grep
и замену), но нам потребуется больше информации о том, как выглядит линия, чтобы помочь вам.sed -i.bak '/firmware_revision/ s/test/production/' myfile.py
Ответы:
Пытаться:
Здесь
/firmware_revision/
действует как условие. Это верно для строк, которые соответствуют регулярному выражению,firmware_revision
и false для других строк. Если условие истинно, выполняется следующая команда. В этом случае, эта команда является командой заменителя , который заменяет первое вхождениеtest
сproduction
.Другими словами, команда
s/test/production/
выполняется только в строках, которые соответствуют регулярному выражениюfirmware_revision
. Все остальные линии проходят без изменений.По умолчанию sed отправляет свой вывод стандартному выводу. Вы, однако, хотели изменить файл на месте. Итак, мы добавили
-i
опцию. В частности,-i.bak
вызывает изменение файла на место с сохранением резервной копии с.bak
расширением.Если вы решили, что команда работает для вас, и вы хотите жить опасно, а не создавать резервную копию, то с GNU sed (Linux) используйте:
В BSD (OSX), напротив,
-i
параметр должен иметь аргумент. Если вы не хотите сохранять резервную копию, укажите для нее пустой аргумент. Таким образом, используйте:редактировать
При редактировании вопроса OP запрашивает каждое вхождение
test
строки, подлежащей заменеproduction
. В этом случае мы добавляемg
опцию к команде замены для глобальной (для этой строки) замены:источник
-i.bak
часть.-i
добавлено.sed
можно сделать ...''
после-i
?sed -i '/firmware_revision/ s/test/production/g' myfile.py
противном случае изменяется только первый экземпляр.На старых машинах со старой школой,
sed
которые не поддерживают опцию-i
:источник
ed
и сделать это в одной строке:printf %s\\n g/firmware_revision/s/test/production/g w q | ed -s myfile.py
ed(1)
не предлагает никаких предлогов, чтобы показать использованиеmktemp(1)
.ed
делается. Вместо тогоmv -f "$TF" myfile.pl
, чтобы использоватьcat "$TF" > myfile.pl && rm -f "$TF"
. Кстати, хорошей практикой является использование имен переменных в нижнем регистре ($tf
вместо$TF
), они гарантированно не конфликтуют с какими-либо встроенными переменными bash (возможно, и с другими оболочками bourne).cat "$TF" > myfile.pl
попробуйте это:touch a b; chmod 0444 a; cat b >a
(Кстати,sed -i
в этом случае тоже не будет работать). Лучше пусть пользователь справится с этим. Re::rm -f "$TF"
не нужно, видитеtrap ... EXIT
. Re:$tf
вместо$TF
: возможно; это вопрос стиля.umask
отличается от оригинала. Что касается переменных в верхнем регистре, то это не просто вопрос стиля - многие люди, которые допустили ошибку, используя верхний регистр PATH, RANDOM или SHELL или что-то еще для своих собственных переменных, нашли трудный путь. (и да, я часто использую переменные верхнего регистра самостоятельно. Я знаю, что это неправильно, я пытаюсь избавиться от этой привычки).