我如何使用sed来更改我的configuration文件,灵活的键和值?

我想search这个expression式的configuration文件:“central.database”。 然后我想将与“central.database”关联的设置更改为“SQLTEST”。

最初configuration文件的布局看起来像这样:

central.database = SQLFIRSTTEST 

这是我希望看起来像sed更换后:

 central.database = SQLTEST 

我正在做一个bash脚本,任何build议,build议或替代解决scheme,欢迎!

(实际上central.databaseSQLTEST都来自bashvariables)


我目前的代码(第三次尝试):

 sshRetValue=$(ssh -p "35903" -i $HOME/sshids/idrsa-1.old ${1} <<EOF sed -i "s/^\($CENTRAL_DB_NAME\s*=\s*\).*\$/\1$CENTRAL_DB_VALUE/" /home/testing.txt; echo $? EOF ) 

错误信息:

 Pseudo-terminal will not be allocated because stdin is not a terminal. sed: -e expression #1, char 58: unknown option to `s' -bash: line 3: EOF: command not found 

Solutions Collecting From Web of "我如何使用sed来更改我的configuration文件,灵活的键和值?"

这是一个示例表达式:

 sed -i 's/^\(central\.database\s*=\s*\).*$/\1SQLTEST/' file.cfg 

如果你想匹配其中的东西,你可以使用另一个分隔符:

 sed -i 's#^\(cent/ral\.data/base\s*=\s*\).*$#\1SQL/TEST#' file.cfg 

或者可变扩展:

 VAL="SQLTEST" sed -i "s/^\(central\.database\s*=\s*\).*\$/\1$VAL/" file.cfg 

在你的例子中:

 sshRetValue=`sed -i "s/^\(\1$CENTRAL_DB_NAME\s*=\s*\).*\$/\1$CENTRAL_DB_VALUE/" /home/testing.txt`; 

$ CENTRAL_DB_NAME之前有一个\ 1,这是无效的。 另外,sed不打印它的返回值。 这是检查返回值的首选方法:

 sed -i "s/^\($CENTRAL_DB_NAME\s*=\s*\).*\$/\1$CENTRAL_DB_VALUE/" /home/testing.txt; sed_return_value=$? 

并最终管道到SSH(未测试):

 sed_return_value=$(ssh server <<EOF sed -i "s/^\($CENTRAL_DB_NAME\s*=\s*\).*\$/\1$CENTRAL_DB_VALUE/" /home/testing.txt; echo $? EOF ) 

-i用于替换输入文件中的数据。 否则sed写入标准输出。

正则表达式是他们自己的领域。 除非有一些特定的功能不能解决你的问题,否则不可能在一个stackoverflow答案中深入解释它们。

 sed -i -e '/central.database =/ s/= .*/= new_value/' /path/to/file 

说明:

  • -i告诉sed将结果保存到输入文件中。 没有它,sed会将结果打印到标准输出。
  • /central.database =/匹配包含斜线之间字符串的行,即“central.database =”。
  • s/OLD/NEW/部分进行了一项修改。 OLD字符串是一个正则表达式, NEW部分是要替换的字符串。
  • 在正则表达式中, .*表示“匹配任何内容”。 所以= .*匹配一个等号,空格,然后是其他任何内容。

我喜欢使用awk ,因为它很容易理解它正在做什么,非常注意分隔符( = )以及必须对未注释的行进行处理:

 awk -v var="my_var" -v new_val="NEW VALUE" \ # set the vars 'BEGIN{FS=OFS="="} # set separator to = match($1, "^\\s*" var "\\s*") { # check if it matches $2=" " new_val # if so, replace the line }1' conf_file # print all lines 

这使用match()来检查模式是否出现在任何给定的行中。 如果确实如此,则用给定的值执行替换。

例如:

 $ cat conf hello my_var= SOME VALUE #my_var = ANOTHER VALUE bye 

让我们将my_var的值my_varNEW VALUE

 $ awk -v var="my_var" -v new_val="NEW VALUE" 'BEGIN{FS=OFS="="}match($1, "^\\s*" var "\\s*") {$2=" " new_val}1' conf hello my_var= NEW VALUE #my_var = ANOTHER VALUE bye 

也可以在shell变量中设置值,然后在-v使用它们:

 $ var="my_var" $ new_value="NEW VALUE" $ awk -v var="$var" -v new_val="$new_value" 'BEGIN{FS=OFS="="}match($1, "^\\s*" var "\\s*") {$2=" " new_val}1' conf 

你当然可以把所有这些放在一个shell函数中,然后你可以正常调用它:

 #!/bin/bash replace () { file=$1 var=$2 new_value=$3 awk -v var="$var" -v new_val="$new_value" 'BEGIN{FS=OFS="="}match($1, "^\\s*" var "\\s*") {$2=" " new_val}1' "$file" } # Call the replace() function with the necessary parameters replace "conf" "my_var" "NEW VALUE" 

执行后,返回

 hello my_var= NEW VALUE #my_var = ANOTHER VALUE bye 

您也可以使脚本以如下方式接收参数: ./script.sh "conf_file" "var_to_replace" "NEW VALUE" ,然后将它们传递给函数。

如果你想替换2个属性文件,你可以使用这个:

 awk -F= 'NR==FNR{A[$1]=$2;next}$1 in A{$2=A[$1]}1' OFS='\=' /tmp/masterfile /opt/props/finalfile.properties > /tmp/tmp.txt && mv -f /tmp/tmp.txt /opt/props/finalfile.properties 

我用这个脚本保持优先

参数$ 1将具有多个配置文件存在的文件夹。 $ 2将具有需要在$ 1路径中替换的属性,并且子路径文件#3将具有需要在$ 2之上覆盖的属性

它也有隐藏的逻辑来检查$ 2和$ 3中存在的密钥的环境变量的存在并给予优先权。

即如果一个密钥存在于最高优先级的环境中。 接下来就是$ 3,旁边就是$ 1文件。

 #!/bin/bash #Usage is propertyReplacer <CONFIG_FOLDER_PATH> <CONFIG_FILE_2ND_PRIORITY> <CONFIG_FILE_1ST_PRIORITY> function propertyReplacer() { filePathToAct="$1" propertiesFilePath="$2" propertiesSecureFilePath="$3" declare -A keyValues while IFS='=' read -r key value; do if [ "$key" == "" ]; then continue elif [[ "$key" =~ ^#.*$ ]]; then continue else echo $key " --> " $value keyValues[$key]=$value fi done < "$propertiesFilePath" if [ ! -f "$propertiesSecureFilePath" ]; then continue else while IFS='=' read -r key value; do if [ "$key" == "" ]; then continue elif [[ "$key" =~ ^#.*$ ]]; then continue else echo $key " --> " $value keyValues[$key]=$value fi done < "$propertiesSecureFilePath" fi for key in ${!keyValues[@]}; do envProp=${key//[@]/} if [ "$(eval echo '$'$envProp)" == "" ]; then echo "Environment key not exist" $envProp else value=$(eval echo '$'$envProp) echo "From Environment " $envProp " --> "$value keyValues[$key]=$value fi done find "$filePathToAct" | while read -r resultFileName; do if [ ! -f "$resultFileName" ]; then continue else echo "Acting on the file $resultFileName" for key in ${!keyValues[@]}; do value=$(echo "${keyValues[${key}]}" | sed 's/\//\\\//g') echo "sed -i 's/$key/$value/g' $resultFileName " eval "sed -i 's/$key/$value/g' $resultFileName " done fi done }