我如何使用sed来更改我的configuration文件,灵活的键和值?
我想search这个expression式的configuration文件:“central.database”。 然后我想将与“central.database”关联的设置更改为“SQLTEST”。
最初configuration文件的布局看起来像这样:
central.database = SQLFIRSTTEST
这是我希望看起来像sed更换后:
central.database = SQLTEST
我正在做一个bash脚本,欢迎任何build议,build议或替代解决scheme!
(实际上central.database
和SQLTEST
都来自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_var
为NEW 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