bash 将一个子字符串替换为 shell 脚本中的另一个字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13210880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Replace one substring for another string in shell script
提问by Zincode
I have "I love Suzi and Marry" and I want to change "Suzi" to "Sara".
我有“I love Suzi and Marry”,我想把“Suzi”改成“Sara”。
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
The result must be like this:
结果必须是这样的:
firstString="I love Sara and Marry"
回答by ruakh
To replace the firstoccurrence of a pattern with a given string, use ${parameter/pattern/string}
:
要用给定的字符串替换第一次出现的模式,请使用:${parameter/pattern/string}
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
echo "${firstString/Suzi/$secondString}"
# prints 'I love Sara and Marry'
To replace alloccurrences, use ${parameter//pattern/string}
:
要替换所有出现,请使用:${parameter//pattern/string}
message='The secret code is 12345'
echo "${message//[0-9]/X}"
# prints 'The secret code is XXXXX'
(This is documented in the Bash Reference Manual, §3.5.3 "Shell Parameter Expansion".)
(这被记录在所述击参考手册,§3.5.3“壳牌参数扩展”。)
Note that this feature is not specified by POSIX — it's a Bash extension — so not all Unix shells implement it. For the relevant POSIX documentation, see The Open Group Technical Standard Base Specifications, Issue 7, the Shell & Utilitiesvolume, §2.6.2 "Parameter Expansion".
请注意,POSIX 未指定此功能——它是 Bash 扩展——因此并非所有 Unix shell 都实现它。有关相关 POSIX 文档,请参阅The Open Group Technical Standard Base Specifications, Issue 7, the Shell & Utilitiesvolume, §2.6.2 "Parameter Expansion"。
回答by Kevin
This can be done entirely with bash string manipulation:
这可以完全通过 bash 字符串操作来完成:
first="I love Suzy and Mary"
second="Sara"
first=${first/Suzy/$second}
That will replace only the first occurrence; to replace them all, double the first slash:
这将仅替换第一次出现;要全部替换它们,请将第一个斜杠加倍:
first="Suzy, Suzy, Suzy"
second="Sara"
first=${first//Suzy/$second}
# first is now "Sara, Sara, Sara"
回答by Roman Kazanovskyi
For Dash all previous posts aren't working
对于 Dash,所有以前的帖子都不起作用
The POSIX sh
compatible solution is:
POSIXsh
兼容的解决方案是:
result=$(echo "$firstString" | sed "s/Suzi/$secondString/")
回答by Kent
try this:
尝试这个:
sed "s/Suzi/$secondString/g" <<<"$firstString"
回答by Camilo Martin
It's better to use bash than sed
if strings have RegExp characters.
使用 bash 比sed
字符串包含 RegExp 字符更好。
echo ${first_string/Suzi/$second_string}
It's portable to Windows and works with at least as old as Bash 3.1.
它可移植到 Windows,并且至少与 Bash 3.1 一样古老。
To show you don't need to worry much about escaping let's turn this:
为了表明你不需要太担心转义,让我们来看看这个:
/home/name/foo/bar
Into this:
进入这个:
~/foo/bar
But only if /home/name
is in the beginning. We don't need sed
!
但前提/home/name
是刚开始。我们不需要sed
!
Given that bash gives us magic variables $PWD
and $HOME
, we can:
鉴于 bash 为我们提供了魔法变量$PWD
和$HOME
,我们可以:
echo "${PWD/#$HOME/\~}"
EDIT:Thanks for Mark Haferkamp in the comments for the note on quoting/escaping ~
.*
编辑:感谢 Mark Haferkamp 在注释中对引用/转义的注释~
。*
Note how the variable $HOME
contains slashes but this didn't break anything.
请注意变量如何$HOME
包含斜杠,但这并没有破坏任何东西。
Further reading: Advanced Bash-Scripting Guide.
If using sed
is a must, be sure to escape every character.
进一步阅读:高级 Bash 脚本指南。
如果sed
必须使用 using ,请确保对每个字符进行转义。
回答by Josh Habdas
If tomorrow you decide you don't love Marry either she can be replaced as well:
如果明天你决定不爱玛丽,她也可以被替换:
today=$(</tmp/lovers.txt)
tomorrow="${today//Suzi/Sara}"
echo "${tomorrow//Marry/Jesica}" > /tmp/lovers.txt
There must be 50 ways to leave your lover.
一定有50种方式可以离开你的爱人。
回答by Nate Revo
Since I can't add a comment. @ruaka To make the example more readable write it like this
因为我无法添加评论。@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}
回答by agc
Pure POSIXshell method, which unlike Roman Kazanovskyi's sed
-based answerneeds no external tools, just the shell's own native parameter expansions. Note that long file names are minimized so the code fits better on one line:
纯POSIXshell 方法,与Roman Kazanovskyi的sed
基于答案不同,不需要外部工具,只需要 shell 自己的本机参数扩展。请注意,长文件名被最小化,因此代码更适合一行:
f="I love Suzi and Marry"
s=Sara
t=Suzi
[ "${f%$t*}" != "$f" ] && f="${f%$t*}$s${f#*$t}"
echo "$f"
Output:
输出:
I love Sara and Marry
How it works:
这个怎么运作:
Remove Smallest Suffix Pattern.
"${f%$t*}"
returns "I love
" if the suffix$t
"Suzi*
" is in$f
"I love
Suzi and Marry
".But if
t=Zelda
, then"${f%$t*}"
deletes nothing, and returns the whole string "I love Suzi and Marry
".This is used to test if
$t
is in$f
with[ "${f%$t*}" != "$f" ]
which will evaluate to trueif the$f
string contains "Suzi*
" and falseif not.If the test returns true, construct the desired string using Remove Smallest Suffix Pattern
${f%$t*}
"I love
" and Remove Smallest Prefix Pattern${f#*$t}
"and Marry
", with the 2ndstring$s
"Sara
" in between.
删除最小后缀模式。 如果后缀“ ”在“ ”中,则
"${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" ]
其中将评估为真如果$f
字符串包含“Suzi*
”的虚假如果不是。如果测试返回true,则使用移除最小后缀模式
${f%$t*}
“I love
”和移除最小前缀模式${f#*$t}
“and Marry
”构建所需的字符串,中间有第二个字符串$s
“Sara
”。
回答by Payam
I know this is old but since no one mentioned about using awk:
我知道这是旧的,但因为没有人提到使用 awk:
firstString="I love Suzi and Marry"
echo $firstString | awk '{gsub("Suzi","Sara"); print}'
回答by Alberto Salvia Novella
echo [string] | sed "s/[original]/[target]/g"
- "s" means "substitute"
- "g" means "global, all matching occurrences"
- “s”的意思是“替代”
- “g”的意思是“全局的,所有匹配的出现”