在外壳脚本中将一个子字符串替换为另一个字符串

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

firstString="I love Suzi and Marry"secondString="Sara"

期望结果:

firstString="I love Sara and Marry"
1403893 次浏览

试试这个:

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

要使用给定字符串替换模式的第一出现,请使用${parameter/pattern/string}

#!/bin/bashfirstString="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参数扩展”中记录。

请注意,POSIX没有指定此功能-它是一个Bash扩展-因此并非所有Unix shell都实现它。有关相关的POSIX留档,请参阅开放组技术标准基础规范,第7期Shell&U实用程序卷,§2.6.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"

对达什来说所有的历史发文都没用

POSIXsh兼容的解决方案是:

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

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

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

如果字符串有正则表达式字符,使用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脚本指南
如果必须使用sed,请务必使用逃避每个字符

如果明天你决定不爱玛丽,她也可以被取代:

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}ormy_string=${full_string/Suzy/Sarah}

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

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

输出:

I love Sara and Marry

它是如何工作的:

  • 删除最小的后缀模式。如果后缀$tSuzi*”在$fI loveSuzi and Marry”中,则"${f%$t*}"返回“I love”。

  • 但是如果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"。

使用AWK

firstString="I love Suzi and Marry"echo "$firstString" | awk '{gsub("Suzi","Sara"); print}'
echo [string] | sed "s|[original]|[target]|g"
  • "s"的意思是"替代"
  • "g"表示"全局,所有匹配的事件"

我找到的唯一方法是将字符串存储在文件中,使用ses然后将文件内容存储在var中:

echo "I love Suzy" > tmp.txtsed -i "s/Suzy/Sarah/" tmp.txtset res=`cat tmp.txt`echo $resrm tmp.txt

我不知道我使用的是哪种shell(如果我键入'sh',我唯一找到的是sh-4.2),但所有经典语法都失败了,比如简单的test=${test2}。它失败了2次:在赋值处(必须使用set)和在${}处。

试试这个:

ls *.ext | awk '{print "mv "$1" "$1".newext"}' | sed "s/.ext.newext/.newext/" | parallel {}

用特殊章程替换第一个匹配项的模式:

${参数/模式/字符串}

用特殊章程替换所有出现的模式:

${参数//模式/字符串}

firstString="I love //Suzi// and Marry"secondString="Sara"firstString="${firstString/\/\/Suzi\/\//"$secondString"}"echo $firstString

它将打印:I love Sara and Marry

使用Sed我们可以很容易地做到

Sed-i"s+$value_to_be_replaced+$with_variable1"一些字符"$with_variable2+g"$file_name

我认为这是您的用例最干净的形式:

firstString="${firstString//Suzi/$secondString}"