我如何使用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 

这是一个示例expression式:

 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=$? 

并最终pipe道到SSH(未testing):

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

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

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

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

说明:

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

我喜欢使用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()来检查模式是否出现在任何给定的行中。 如果确实如此,则用给定的值执行replace。

例如:

 $ 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 

也可以在shellvariables中设置值,然后在-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" ,然后将它们传递给函数。

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

 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