Intereting Posts
Как получить незначительную и серьезную ошибку страницы для отдельных или групп процессов? USB-ключ не устанавливается при загрузке, чтобы разблокировать систему LUKS Base64 декодирует и перезаписывает файл Замедленная подстановка команды Bash не работает Как отключить кеши L1 и L2 процессора? ssh для private-ip Нет сетевого подключения в CentOS 6.3 Минимальное значение в разделе VMWare Player Подсчитайте количество процессов и отправьте электронное письмо нескольким людям, если оно превышает определенный предел Как подключить html к w3m? Как модули ядра Linux становятся доступными в пакете ядра Linux-дистрибутива? Что такое эквивалент Linux для C: \ Program Files? Как мне откатить установку и удаление yum? Режим eldoc позволяет emacs использовать 100% процессор Настройка беспроводной сети на FreeBSD: маршрутизатор показывает, что беспроводное устройство подключено, но не может выполнить пинг Копирование текущей командной строки в буфер обмена

Изменение существующего файла непосредственно для замены «foo» на «bar» ТОЛЬКО для строк, содержащих «baz»,

У меня есть файл food.txt следующим образом:

mangoes|foo|faa oranges|foo|faa chocolates|foo|baz 

Я пытаюсь заменить foo на bar, если условие baz выполнено. (хотел бы использовать здесь регулярное выражение b * z)
В настоящее время используется команда sed ниже, но это напрямую не изменяет существующий файл. Я также не могу использовать регулярное выражение (b * z).

 sed '/baz/s/foo/bar/g' food.txt 

Пожалуйста, предложите другой способ, кроме «sed», напрямую изменить существующий файл.

PS: Я попробовал sed -i но я бы хотел использовать другую команду, кроме sed.
Я использую mobaxterm (ОС – Windows)

Фактический лучший инструмент для автоматических текстовых изменений – ex .

Хотя это можно было бы вызвать прямо, я нашел в MobaXterm, что вместо этого мне нужно позвонить vim -e .

Таким образом, лучший способ сделать это автоматическое редактирование в MobaXterm (и который также будет работать в других системах * nix):

 printf '%s\n' 'g/b.*z/s/foo/bar/g' x | vim -es food.txt 

Чтобы быть полностью совместимым с POSIX, необходимо изменить его только на:

 printf '%s\n' 'g/b.*z/s/foo/bar/g' x | ex -s food.txt 

Однако вызов команды ex может работать неправильно на MobaXterm (это не происходит при моей установке.) Попробуйте версию vim -es команды, если ex версия завершилась с ошибкой.

В этом случае я не вижу ничего плохого в использовании sed . Это правильный инструмент для работы.

Ваша команда работает хорошо (по данным):

 $ sed '/baz/s/foo/bar/g' food.txt mangoes|foo|faa oranges|foo|faa chocolates|bar|baz 

Используя регулярное выражение для соответствия любой строке, начинающейся с |b и заканчивающейся в z в конце строки (вместо baz любом месте строки):

 $ sed '/|b.*z$/s/foo/bar/g' food.txt mangoes|foo|faa oranges|foo|faa chocolates|bar|baz 

Чтобы внести изменения в файл (с помощью GNU sed ):

 $ sed -i '/|b.*z$/s/foo/bar/g' food.txt 

или (с любым выполнением sed ):

 $ sed '/|b.*z$/s/foo/bar/g' food.txt >tmpfile && mv tmpfile food.txt 

Использование awk с gsub() :

 awk '/baz$/ {gsub("foo", "bar")};1' food.txt 
  • Используйте любой шаблон Regex для соответствия вместо /baz$/ , если хотите

  • если шаблон совпадает, выполните gsub() чтобы заменить нужные строки


Для редактирования inpace в последней версии GNU awk (> = 4.1.0) есть опция модификации inplace:

 awk -i inplace '/baz$/ {gsub("foo", "bar")};1' food.txt 

В противном случае вы можете использовать sponge из GNU moreutils или использовать временный файл:

 awk '/baz$/ {gsub("foo", "bar")};1' food.txt >temp_food.txt && \ mv temp_food.txt food.txt 

Пример:

 $ cat file.txt mangoes|foo|faa oranges|foo|faa chocolates|foo|baz $ awk '/baz$/ {gsub("foo", "bar")};1' file.txt mangoes|foo|faa oranges|foo|faa chocolates|bar|baz 

Хотя я понятия не имею, почему вы не хотите использовать sed -i который делает именно то, что вам нужно, другой вариант будет perl :

 $ perl -pe 's/foo/bar/g if /b*z/' food.txt mangoes|foo|faa oranges|foo|faa chocolates|bar|baz 

Параметр -pe означает «распечатывать каждую строку входного файла после применения сценария к нему.

И вы можете использовать -i для редактирования файла на месте:

 perl -i -pe 's/foo/bar/g if /b*z/' food.txt 

Обратите внимание, что регулярное выражение b*z означает «совпадение 0 или более b за которым следует z . Он будет работать здесь, потому что b*z соответствует bar , игнорируя b и a и просто сопоставляя z . Другими словами, он будет соответствовать любому z так как любой z будет примером 0 b за которым следует z . Я думаю, что вы, вероятно, хотите использовать, это b. * z (ab следует 0 или более символов, а затем az):

 perl -i -pe 's/foo/bar/g if /b.*z/' food.txt