使SED命令适用于任何变量

时间:2021-05-04 00:38:33

deploy.sh

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

config.conf

deloy="PLACEHOLDER_USERNAME"
pass="PLACEHOLDER_PASSWORD"

This file puts my variables defined in deploy into my config file. I can't source the file so I want put my variables in this way.

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

Question

I want a command that is generic to work for all placeholder variables using some sort of while loop rather than needing one command per variable. This means any term starting with placeholder_ in the file will try to be replaced with the value of the variable defined already in deploy.sh

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

All variables should be set and not empty. I guess if there is the ability to print a warning if it can't find the variable that would be good but it isn't mandatory for this.

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

2 个解决方案

#1


1  

Basically, use shell code to write a sed script and then use sed -i .bak -f sed.script config.conf to apply it:

基本上,使用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

The main 'tricks' here are:

这里的主要“技巧”是:

  1. knowing that ${!var} expands to the value of the variable named by $var, and
  2. 知道$ {!var}扩展为$ var命名的变量的值,和
  3. knowing that sed will take a script full of commands via -f sed.script, and
  4. 知道sed会通过-f sed.script获取一个充满命令的脚本
  5. knowing how to use trap to ensure temporary files are cleaned up.
  6. 知道如何使用陷阱来确保清理临时文件。

You could also use sed -e "s/.../.../" -e "s/.../.../" -i .bak config.conf too, but the script file is easier, I think, especially if you have more than 2 values to substitute. If you want to go down this route, use a bash array to hold the arguments to sed. A more careful script would use at least $$ in the script file name, or use mktemp to create the temporary file.

您也可以使用sed -e“s /.../.../”-e“s /.../.../”-i .bak config.conf,但脚本文件更容易,我想想,特别是如果你有超过2个值可以替代。如果你想沿着这条路线走,请使用bash数组来保存sed的参数。更仔细的脚本将在脚本文件名中使用至少$$,或使用mktemp创建临时文件。


Revised answer

The trouble is, although much closer to being generic, it is still not generic since I have to manually put in what variables I want to change. Can it not be more like "for each placeholder_, find the variable in deploy.sh and add that variable, so it can work for any number of variables.

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

So, find what the variables are in the configuration file, then apply the techniques of the previous answer to solve that problem:

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

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

This code still pulls the values from the environment. You need to clarify what is required if you want to extract the settings from the shell script, but it can be done — the script will have to be sufficiently self-aware to find its source so it can search it for the names. But the basics are in this answer; the rest is a question of tinkering until it does what you need.

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

#2


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
   }
"

call like this: YourScript.ksh YourTemplateFile YourDataSourceFile where:

这样调用:YourScript.ksh YourTemplateFile YourDataSourceFile其中:

  • YourTemplateFile is the file that contain the structure with generic value like deloy="PLACEHOLDER_USERNAME"
  • YourTemplateFile是包含具有通用值的结构的文件,如deloy =“PLACEHOLDER_USERNAME”
  • YourDataSourceFile is the file that contain all the peer Generic value = specific value like USERNAME="Tom"
  • YourDataSourceFile是包含所有对等Generic值=特定值的文件,如USERNAME =“Tom”

#1


1  

Basically, use shell code to write a sed script and then use sed -i .bak -f sed.script config.conf to apply it:

基本上,使用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

The main 'tricks' here are:

这里的主要“技巧”是:

  1. knowing that ${!var} expands to the value of the variable named by $var, and
  2. 知道$ {!var}扩展为$ var命名的变量的值,和
  3. knowing that sed will take a script full of commands via -f sed.script, and
  4. 知道sed会通过-f sed.script获取一个充满命令的脚本
  5. knowing how to use trap to ensure temporary files are cleaned up.
  6. 知道如何使用陷阱来确保清理临时文件。

You could also use sed -e "s/.../.../" -e "s/.../.../" -i .bak config.conf too, but the script file is easier, I think, especially if you have more than 2 values to substitute. If you want to go down this route, use a bash array to hold the arguments to sed. A more careful script would use at least $$ in the script file name, or use mktemp to create the temporary file.

您也可以使用sed -e“s /.../.../”-e“s /.../.../”-i .bak config.conf,但脚本文件更容易,我想想,特别是如果你有超过2个值可以替代。如果你想沿着这条路线走,请使用bash数组来保存sed的参数。更仔细的脚本将在脚本文件名中使用至少$$,或使用mktemp创建临时文件。


Revised answer

The trouble is, although much closer to being generic, it is still not generic since I have to manually put in what variables I want to change. Can it not be more like "for each placeholder_, find the variable in deploy.sh and add that variable, so it can work for any number of variables.

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

So, find what the variables are in the configuration file, then apply the techniques of the previous answer to solve that problem:

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

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

This code still pulls the values from the environment. You need to clarify what is required if you want to extract the settings from the shell script, but it can be done — the script will have to be sufficiently self-aware to find its source so it can search it for the names. But the basics are in this answer; the rest is a question of tinkering until it does what you need.

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

#2


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
   }
"

call like this: YourScript.ksh YourTemplateFile YourDataSourceFile where:

这样调用:YourScript.ksh YourTemplateFile YourDataSourceFile其中:

  • YourTemplateFile is the file that contain the structure with generic value like deloy="PLACEHOLDER_USERNAME"
  • YourTemplateFile是包含具有通用值的结构的文件,如deloy =“PLACEHOLDER_USERNAME”
  • YourDataSourceFile is the file that contain all the peer Generic value = specific value like USERNAME="Tom"
  • YourDataSourceFile是包含所有对等Generic值=特定值的文件,如USERNAME =“Tom”