У меня есть «Я люблю Сьюзи и Жениться», и я хочу изменить «Сьюзи» на «Сара».
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
Результат должен быть таким:
firstString="I love Sara and Marry"
У меня есть «Я люблю Сьюзи и Жениться», и я хочу изменить «Сьюзи» на «Сара».
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
Результат должен быть таким:
firstString="I love Sara and Marry"
Ответы:
Чтобы заменить первое вхождение шаблона данной строкой, используйте :${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 Reference Manual , §3.5.3 "Shell Параметр Expansion" .)
Обратите внимание, что эта функция не указана в POSIX - это расширение Bash - поэтому не все оболочки Unix реализуют ее. Соответствующую документацию POSIX см. В разделе Базовые технические спецификации стандарта Open Group, выпуск 7 , том Shell & Utilities , §2.6.2 «Расширение параметров» .
\n
в этом контексте будет представлять себя, а не перевод строки. Сейчас у меня нет возможности использовать Bash для тестирования, но вы должны написать что-то вроде $STRING="${STRING/$'\n'/<br />}"
. (Хотя вы, вероятно, хотите STRING//
- заменить все - вместо просто STRING/
.)
echo ${my string foo/foo/bar}
. Тебе понадобитсяinput="my string foo"; echo ${input/foo/bar}
//
непосредственного упоминания , в ней упоминается, что происходит, «если шаблон начинается с /
« »(что даже не является точным, поскольку остальная часть этого предложения предполагает, что дополнительное на /
самом деле не является частью шаблон) - но я не знаю лучшего источника.
Это можно сделать полностью с помощью манипуляции с 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"
Для Dash все предыдущие посты не работают
POSIX- sh
совместимое решение:
result=$(echo "$firstString" | sed "s/Suzi/$secondString/")
result=$(echo $firstString | sed "s/Suzi/$secondString/g")
echo
аргумента. Он обманчиво работает без кавычек с простыми строками, но легко разбивается на любую нетривиальную входную строку (неправильный интервал, метасимволы оболочки и т. Д.).
попробуй это:
sed "s/Suzi/$secondString/g" <<<"$firstString"
Лучше использовать 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/\~}"
РЕДАКТИРОВАТЬ: Спасибо за Марк Haferkamp в комментариях за примечание о цитировании / экранирование ~
. *
Обратите внимание, что переменная $HOME
содержит косые черты, но это ничего не сломало.
Дополнительная информация: Расширенное руководство по написанию сценариев .
Если использование sed
является обязательным, обязательно избегайте каждого символа .
sed
с pwd
командой , чтобы избежать определения новой переменной каждый раз , когда мои собственные $PS1
пробеги. Предоставляет ли Bash более общий способ, чем магические переменные, использовать вывод команды для замены строки? Что касается вашего кода, мне пришлось избежать того, ~
чтобы Bash не расширил его до $ HOME. Кроме того, что делает #
в вашей команде?
~
»: обратите внимание, как я цитировал материал. Не забывайте всегда цитировать вещи! И это работает не только для магических переменных: любая переменная способна к подстановкам, получению длины строки и многим другим в bash. Поздравляю с попыткой $PS1
быстро: вам также может быть интересно, $PROMPT_COMMAND
если вам удобнее использовать другой язык программирования и вы хотите написать скомпилированное приглашение.
echo "${PWD/#$HOME/~}"
не заменяет мой $HOME
на ~
. Замена ~
на \~
или '~'
работает. Любая из них работает на Bash 4.2.53 в другом дистрибутиве. Можете ли вы обновить свой пост, чтобы процитировать или избежать ~
для лучшей совместимости? Под вопросом «магические переменные» я имел в виду следующее: могу ли я использовать подстановку переменных в Bash, например, на выходе, uname
не сохраняя его сначала как переменную? Что касается моего личного $PROMPT_COMMAND
, это сложно .
Если завтра вы решите, что не любите замуж, то ее тоже можно заменить:
today=$(</tmp/lovers.txt)
tomorrow="${today//Suzi/Sara}"
echo "${tomorrow//Marry/Jesica}" > /tmp/lovers.txt
Должно быть 50 способов расстаться с любовником.
Поскольку я не могу добавить комментарий. @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}
Чистый POSIX метод оболочки, который в отличии от Roman Kazanovskyi «s sed
-На ответа не требует никаких внешних инструментов, только собственные родные оболочечных расширения параметров . Обратите внимание, что длинные имена файлов сведены к минимуму, поэтому код лучше помещается в одну строку:
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, если нет.
Если тест возвращает истинный , построить нужную строку , используя Удалить Наименьший суффиксов Pattern ${f%$t*}
« I love
» и удалить Наименьший префикс Pattern ${f#*$t}
« and Marry
», с 2 - ой строке $s
« Sara
» между ними.
Я знаю, что это старый, но так как никто не упомянул об использовании awk:
firstString="I love Suzi and Marry"
echo $firstString | awk '{gsub("Suzi","Sara"); print}'
echo [string] | sed "s/[original]/[target]/g"