如何在Bash中用另一个变量的值替换变量中的占位符字符或单词?

37

我想编写一个简单的Bash脚本。我有一个简单的“模板”变量:

template = "my*appserver"

我有一个函数(get_env()),它返回值为devqalive。我想调用get_env,然后使用返回的值替换template变量,并将其与星号交换。因此:

# Returns "dev"
server = get_env

# Prints "mydevappserver"
template = string_replace(server, template)

或者:

# This time, it returns "live"
server = get_env

# Prints "myliveappserver"
template = string_replace(server, template)

我应该使用什么替代string_replace()函数来完成绑定?

8个回答

66

Bash可以自行进行字符串替换:

template='my*appserver'
server='live'
template="${template/\*/$server}"

请参阅高级Bash脚本指南,了解更多有关字符串替换的详细信息。

因此,对于一个Bash函数:

function string_replace {
    echo "${1/\*/$2}"
}

并且使用:

template=$(string_replace "$template" "$server")

3
这个代码("${1/\*/$2}")只会替换脚本中第一次出现的内容: - arcol
7
解决方案非常简单,正确的形式是用"${1//*/$2}"替换所有出现的内容。 - arcol
1
读者应该对指向ABS的链接持谨慎态度。在某些方面,它是一个非常有用的资源,但它存在内容和呈现问题。 - tripleee

41

在Bash脚本中进行字符串替换,比如可以使用sed命令实现:

template=$(echo $template | sed 's/old_string/new_string/g')

这将用新字符串(new_string)替换模板变量中的旧字符串(old_string)。


如果我想要进行大量替换,那么sed调用的次数肯定会影响我的脚本性能。 - iBug

8

由于没有人提到,这里有一个使用printf的有趣方法。占位符必须是%s而不是*

# use %s as the place-holder
template="my%sappserver"

# replace the place-holder by 'whatever-you-like':
server="whatever-you-like"
printf -v template "$template" "$server"

完成!

如果你想要一个函数来做这个事情(注意其他提到函数的解决方案都使用了丑陋的子shell):

#!/bin/bash

# This wonderful function should be called thus:
# string_replace "replacement string" "$placeholder_string" variable_name
string_replace() {
    printf -v $3 "$2" "$1"
}

# How to use it:
template="my%sappserver"
server="whatever-you-like"

string_replace "$server" "$template" destination_variable

echo "$destination_variable"

完成了(再次)!

希望您喜欢它……现在,根据您的需求进行调整!

备注。 使用printf的这种方法似乎比bash的字符串替换略快。而且这里根本没有子shell!哇,这是西部最好的方法。

有趣。 如果您喜欢有趣的东西,可以将上面的函数string_replace编写为

string_replace() {
    printf -v "$@"
}

# but then, use as:
string_replace destination_variable "$template" "$server"

3

是的,就像其他人说的那样,可以使用'sed'或者将模板分成两个变量然后动态构建。例如:

templateprefix="my"
templatesuffix="appserver"

server=get_env

template=${templateprefix}${server}${templatesuffix}

2

根据 @Spencer Rathbun 的回答,也可以这样做:

   function string_replace {
        #DOC: "${string/match/replace}"
        string=$1
        echo "${string/$2/$3}"
    }

    template='my__patternReplacing__appserver'
    match='__patternReplacing__'
    replace='live'

    template=$(string_replace "$template" "$match" "$replace")

1

我需要做类似于这样的事情,但我需要使用sed,并且替换子句需要包括一个变量。最终我得到了这个。

其中变量名为$puttyline。

sed "s/\(\[remote .origin.\]\)/\1\n$puttyline/"

所以sed搜索[remote "origin"]并记住匹配项,然后在其右侧插入一行,其中包含变量$puttyline中的任何内容。

但是,如果$puttyline包含sed会反应的任何特殊字符,例如\或$,则可能会变得很丑陋。您必须使用另一个sed调用提前转义它们,或者......在bash中执行更智能的操作,我对bash不太熟悉。例如,要对所有反斜杠进行双重转义:

sed 's/\\/\\\\/g'

如果$puttline包含特殊字符,那么会不会出现编码问题? - Frank Schwieterman
@FrankSchwieterman 这实际上更取决于您的输入编码是否与输出匹配,而不是这个解决方案的功能如何。 - Chris Moschini

0

网上有很多帖子可用,但对我有效的是以下内容。

有两种方法可以实现这一点,如果您想在文件中用另一个字符串替换一个字符串(我的旧字符串带有特殊字符 :)),则使用此方法:

sed -i '/oldtext:/c\newtext: Rahul'  ./printName.txt

其次,如果你想要搜索一个字符串并将其替换为你的变量,那么可以这样做:

#here im concatinating two key + value(myvariable).
firstkey="oldtext: old"

key="newtext: "

value=$(cat ./variableStoredHere.txt)

key+=$value

执行以下命令的结果将会是 oldtext: old

echo $firstkey 

以下命令的结果将是newtext: Rahul

echo $key 


sed -i "s/$firstkey/$key/g" ./printName.txt  

0
这是一个包装的bash脚本

示例:

$ search_and_replace.sh "test me out" "test me" ez
ez out

search_and_replace.sh

#!/bin/bash
function show_help()
{
  echo ""
  echo "usage: SUBJECT SEARCH_FOR REPLACE_WITH"
  echo ""
  echo "e.g. "
  echo ""
  echo "test t a                     => aesa"
  echo "'test me out' 'test me' ez   => ez out"
  echo ""

  exit
}

if [ "$1" == "help" ]
then
  show_help
  exit
fi
if [ -z "$3" ]
then
  show_help
  exit
fi

SUBJECT=$1
SEARCH_FOR=$2
REPLACE_WITH=$3

echo "$SUBJECT" | sed -e "s/$SEARCH_FOR/$REPLACE_WITH/g"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接