Как найти все вхождения строки в файле и заменить на другую строку

возможно тривиально но все же. Есть файл 'file.txt' - в нем некоторое количество строк:

export ENV1 = '1'
export ENV2 = '2'
export ENV3 = '3'

Необходимо bash скриптом находить строку где есть вхождение ENV1 и заменять на другое значение - ENV1 = '5'

Пробовал - sed -i '' 's/ENV1/export ENV1 = '5'/g' file.txt но безрезультатно - не заменяет а добавляет. ОC - macos catalina. Cпасибо за помощь.


Ответы (2 шт):

Автор решения: Senior Pomidor

проблема в том, что sed в маке не тот же sed, что вы привыкли. Вам нужно поставить GNU Sed

для установки выполните

brew install gnu-sed 

появится новая программа gsed, тогда команда gsed -i '' 's/ENV1/export ENV1 = '5'/g' file.txt отработает корректно.

если хотите полностью заменить sed, то нужно исполнить просто brew install gnu-sed --with-default-names, при котором в /usr/local/bin/ появится нужный sed

Почему у вас возникает данная проблема?

*'s/ENV1/export ENV1 = '5'/g'*
  • s/../g - заменить все строки(s) во всем файле(g)
  • между ними написано: искомое значение ENV1 заменить на export ENV1 = '5', поэтому, в конце вы получаете export export ENV1 = 5 = '1'

я бы порекомендовал сделать так

1) sed -i -e "s/export ENV1.*/export ENV1 = '5'/g" file.txt 
2) sed -i    "s/export ENV1 = '1'/export ENV1 = '5'/g"  file.txt 

в первом варианте заменить все, что удовлетворяет регулярку на новое, а во втором - заменить точный текст.

оба варианта работают на маке. gsed не нужен

UPDATE

Что делать, если нужно менять URL?

менять разделитьель с / на ~

  /tmp VALUE="http://127.0.0.1"
VALUE="http://127.0.0.1"
➜  /tmp cat test.txt | sed  -e 's~export ENV1.*~export ENV1='"${VALUE}"'~'
cat test.txt | sed  -e 's~export ENV1.*~export ENV1='"${VALUE}"'~'
export ENV1=http://127.0.0.1
export ENV2 = '2'
export ENV3 = '3'
→ Ссылка
Автор решения: Fat-Zer

Можно как-то так:

sed -i '' "/ENV1 =/s/'.*'/'5'/g" file.txt

если на какие-то особенностий синтаксиса BSD'яшного sed'а не напоролся... само собой выражение можно расширить/сузить в зависимости от допустимого содержимого конкретного файла...

→ Ссылка