1129

我有“我爱 Suzi 和 Marry”,我想把“Suzi”改成“Sara”。

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

结果必须是这样的:

firstString="I love Sara and Marry"
4

10 回答 10

1905

要用给定的字符串替换第一次出现的模式,请使用:${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 “Shell Parameter Expansion”中。)

请注意,POSIX 并未指定此功能(它是 Bash 扩展),因此并非所有 Unix shell 都实现它。有关相关 POSIX 文档,请参阅The Open Group Technical Standard Base Specifications, Issue 7Shell & Utilities卷,第 2.6.2 节“参数扩展”

于 2012-11-03T16:05:06.823 回答
281

这可以完全通过 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"
于 2012-11-03T16:05:35.710 回答
171

对于 Dash,以前的所有帖子都不起作用

POSIXsh兼容的解决方案是:

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

这将替换每行输入的第一次出现。添加一个/g标志来替换所有匹配项:

result=$(echo "$firstString" | sed "s/Suzi/$secondString/g")
于 2014-04-09T08:56:20.060 回答
76

试试这个:

 sed "s/Suzi/$secondString/g" <<<"$firstString"
于 2012-11-03T16:04:21.233 回答
55

使用 Bash 比使用sed正则表达式字符更好。

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/\~}"

感谢 Mark Haferkamp 在评论中对引用/转义的注释~。*

请注意变量如何$HOME包含斜杠,但这并没有破坏任何东西。

进一步阅读:高级 Bash 脚本指南
如果 usingsed是必须的,请务必转义每个字符

于 2014-06-22T03:43:53.667 回答
25

如果明天你决定不爱 Marry,她也可以被替换:

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

离开你的爱人一定有50种方法。

于 2017-07-11T02:39:54.983 回答
18
echo [string] | sed "s/[original]/[target]/g"
  • “s”的意思是“替代”
  • “g”表示“全局,所有匹配的事件”
于 2020-05-09T18:09:19.350 回答
16

因为我不能添加评论。@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}
于 2019-03-12T21:50:22.430 回答
9

使用AWK

firstString="I love Suzi and Marry"
echo $firstString | awk '{gsub("Suzi","Sara"); print}'
于 2019-09-18T22:40:21.450 回答
8

POSIX shell 方法,与Roman Kazanovskyised基于答案不同,它不需要外部工具,只需要 shell 自己的本机参数扩展。请注意,长文件名已最小化,因此代码更适合一行:

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$tSuzi*$fI love Suzi and Marry

  • 但是如果t=Zelda, 那么"${f%$t*}"什么都不删除,并返回整个字符串“ I love Suzi and Marry”。

  • 这用于测试 if $tis in $fwith which如果字符串包含 " "[ "${f%$t*}" != "$f" ]则评估为true ,否则为false$fSuzi*

  • 如果测试返回true ,则使用Remove Smallest Suffix Pattern ${f%$t*} " I love" 和Remove Smallest Prefix Pattern ${f#*$t} " "构造所需的字符串and Marry第二个字符串$s" Sara" 介于两者之间。

于 2019-04-27T06:24:41.963 回答