Замените одну подстроку для другой строки в оболочке script

У меня есть "Я люблю Suzi и Marry", и я хочу изменить "Suzi" на "Sara".

#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...

Результат должен быть таким:

firstString="I love Sara and Marry"

Ответ 1

Чтобы заменить первое вхождение шаблона заданной строкой, используйте ${parameter/pattern/string}:

#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
echo "${firstString/Suzi/$secondString}"    
# prints 'I love Sara and Marry'

Чтобы заменить все вхождения, используйте ${parameter//pattern/string}:

message='The secret code is 12345'
echo "${message//[0-9]/X}"           
# prints 'The secret code is XXXXX'

(Это задокументировано в Справочном руководстве Bash, §3.5.3 "Расширение параметров оболочки".)

Обратите внимание, что эта функция не указана в POSIX - это расширение Bash - поэтому не все оболочки Unix реализуют ее. Соответствующую документацию по POSIX см. В разделе Базовые технические характеристики стандарта Open Group, выпуск 7, том Shell & Utilities, §2.6.2 "Расширение параметров".

Ответ 2

Это можно сделать полностью с помощью bash манипуляции с строкой:

first="I love Suzy and Mary"
second="Sara"
first=${first/Suzy/$second}

Это заменит только первое вхождение; чтобы заменить их все, удвойте первую косую черту:

first="Suzy, Suzy, Suzy"
second="Sara"
first=${first//Suzy/$second}
# first is now "Sara, Sara, Sara"

Ответ 3

попробуйте следующее:

 sed "s/Suzi/$secondString/g" <<<"$firstString"

Ответ 4

Для Dash все предыдущие посты не работают

Совместимое решение POSIX sh:

result=$(echo "$firstString" | sed "s/Suzi/$secondString/")

Ответ 5

Лучше использовать bash, чем sed если строки имеют символы RegExp.

echo ${first_string/Suzi/$second_string}

Он переносится в Windows и работает, по крайней мере, так же стара, как Bash 3.1.

Чтобы показать, что вам не нужно много волноваться об экранировании, позвольте включить это:

/home/name/foo/bar

В этом:

~/foo/bar

Но только если /home/name в начале. Нам не нужно sed !

Учитывая, что bash дает нам магические переменные $PWD и $HOME, мы можем:

echo "${PWD/#$HOME/\~}"

EDIT: Спасибо за Марка Хаферкампа в комментариях к заметке о цитировании/побеге ~. *

Обратите внимание, как переменная $HOME содержит слэши, но это ничего не сломало.

Дальнейшее чтение: Расширенный Bash-Scripting Guide.
Если использование sed является обязательным, обязательно избегайте каждого символа.

Ответ 6

Если завтра вы решите, что не любите Marry, ее тоже можно заменить:

today=$(</tmp/lovers.txt)
tomorrow="${today//Suzi/Sara}"
echo "${tomorrow//Marry/Jesica}" > /tmp/lovers.txt

Должно быть 50 способов оставить своего любовника.

Ответ 7

Поскольку я не могу добавить комментарий. @ruaka Чтобы сделать пример более читабельным, напишите это так

full_string="I love Suzy and Mary"
search_string="Suzy"
replace_string="Sara"
my_string=${full_string/$search_string/$replace_string}
or
my_string=${full_string/Suzy/Sarah}

Ответ 8

Метод POSIX, который, в отличие от ответа Романа Казановского sed -based, не нуждается во внешних инструментах, только в собственных расширениях собственных параметров оболочки. Обратите внимание, что длинные имена файлов сведены к минимуму, поэтому код лучше помещается в одну строку:

f="I love Suzi and Marry"
s=Sara
t=Suzi
[ "${f%$t*}" != "$f" ] && f="${f%$t*}$s${f#*$t}"
echo "$f"

Выход:

I love Sara and Marry

Как это устроено:

  • Удалить самый маленький шаблон суффикса. "${f%$t*}" возвращает " I love ", если суффикс $t " Suzi* " находится в $f " I love Suzi and Marry ".

  • Но если t=Zelda, то "${f%$t*}" ничего не удаляет и возвращает всю строку " I love Suzi and Marry ".

  • Это используется для проверки того, находится ли $t в $f с помощью [ "${f%$t*}" != "$f" ] что будет иметь значение true, если строка $f содержит " Suzi* ", и значение false, если нет.,

  • Если тест возвращает значение true, создайте нужную строку, используя команду "Удалить наименьший суффикс" ${f%$t*} " I love " и "Удалить наименьший префикс" ${f#*$t} " and Marry " со второй строкой $s " Sara " между ними.

Ответ 9

Я знаю, что это старый, но так как никто не упомянул об использовании awk:

    firstString="I love Suzi and Marry"
    echo $firstString | awk '{gsub("Suzi","Sara"); print}'