使SED命令适用于任何变量

时间:2013-11-27 14:37:58

标签: linux bash shell sed debian

deploy.sh

USERNAME="Tom"
PASSWORD="abc123"
FILE="config.conf"
sed -i "s/\PLACEHOLDER_USERNAME/$USERNAME/g" $FILE
sed -i "s/\PLACEHOLDER_PASSWORD/$PASSWORD/g" $FILE

config.conf

deloy="PLACEHOLDER_USERNAME"
pass="PLACEHOLDER_PASSWORD"

此文件将我在deploy中定义的变量放入我的配置文件中。我无法获取文件,所以我想以这种方式放置我的变量。

问题

我想要一个通用的命令,使用某种while循环而不是每个变量需要一个命令来为所有占位符变量工作。这意味着文件中以placeholder_开头的任何术语都将尝试替换为deploy.sh中已定义的变量的值

应设置所有变量而不是空。我想如果有能力打印警告,如果它找不到好的变量,但它不是强制性的。

2 个答案:

答案 0 :(得分:1)

基本上,使用shell代码编写sed脚本,然后使用sed -i .bak -f sed.script config.conf来应用它:

trap "rm -f sed.script; exit 1" 0 1 2 3 13 15

for var in USERNAME PASSWORD
do
    echo "s/PLACEHOLDER_$var/${!var}/"
done > sed.script

sed -i .bak -f sed.script config.conf

rm -f sed.script
trap 0

这里的主要“伎俩”是:

  1. 知道${!var}扩展为$var命名的变量的值,
  2. 知道sed将通过-f sed.script
  3. 获取充满命令的脚本
  4. 知道如何使用trap来确保清理临时文件。
  5. 您也可以使用sed -e "s/.../.../" -e "s/.../.../" -i .bak config.conf,但我认为脚本文件更容易,特别是如果要替换的值超过2个。如果您想沿着这条路线前进,请使用bash数组来保存sed的参数。更仔细的脚本在脚本文件名中至少使用$$,或使用mktemp创建临时文件。


    修订答案

      

    麻烦的是,虽然更接近通用,但它仍然不是通用的,因为我必须手动输入我想要改变的变量。是不是更像“为每个占位符_,在deploy.sh中找到变量并添加该变量,因此它可以适用于任意数量的变量。

    因此,找到配置文件中的变量,然后应用前一个答案的技术来解决该问题:

    trap "rm -f $tmp; exit 1" 0 1 2 3 13 15
    
    for file in "$@"
    do
    
        for var in $(sed 's/.*PLACEHOLDER_\([A-Z0-9_]*\).*/\1/' "$file")
        do
            value="${!var}"
            [ -z "$value" ] && { echo "$0: variable $var not set for $file" >&2; exit 1; }
            echo "s/PLACEHOLDER_$var/$value/"
        done > $tmp
    
        sed -i .bak -f $tmp "$file"
    
        rm -f $tmp
    
    done
    
    trap 0
    

    此代码仍会从环境中提取值。如果要从shell脚本中提取设置,则需要说明所需的内容,但是可以这样做 - 脚本必须具有足够的自我意识才能找到其来源,以便可以在其中搜索名称。但基本是在这个答案;其余的是一个修修补补的问题,直到它完成你需要的东西。

答案 1 :(得分:0)

#!/bin/ksh
TemplateFile=$1
SourceData=$2

(sed 's/.*/#V0r:PLACEHOLDER_&:r0V#/' ${SourceData}; cat ${TemplateFile}) | sed -n "

s/$/²/
H

$  {
   x
   s/^\(\n *\)*//
# also reset t flag
   t varxs

:varxs
   s/^#V0r:\([a-zA-Z0-9_]\{1,\}\)=\([^²]*\):r0V#²\(\n.*\)\"\1\"/#V0r:\1=\2:r0V#²\3\2/
   t varxs

# clean the line when no more occurance in text
   s/^[^²]*:r0V#²\n//

# and next
   t varxs


# clean the  marker
   s/²\(\n\)/\1/g
   s/²$//

# display the result
   p
   }
"

这样打电话:YourScript.ksh YourTemplateFile YourDataSourceFile其中:

  • YourTemplateFile是包含具有通用值的结构的文件,如deloy="PLACEHOLDER_USERNAME"
  • YourDataSourceFile是包含所有对等Generic值=特定值的文件,如USERNAME="Tom"