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

pro*_*007 38 linux bash sed

我想在配置文件中搜索此表达式:"central.database".然后,我想将与"central.database"关联的设置更改为"SQLTEST".

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

central.database = SQLFIRSTTEST
Run Code Online (Sandbox Code Playgroud)

这是我希望它在sed替换后看起来像:

central.database = SQLTEST
Run Code Online (Sandbox Code Playgroud)

我在bash脚本中这样做,欢迎任何建议,建议或替代解决方案!

(其实都central.databaseSQLTEST这里来自bash的变量.)


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

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
)
Run Code Online (Sandbox Code Playgroud)

错误信息:

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
Run Code Online (Sandbox Code Playgroud)

Joh*_*ica 86

sed -i -e '/central.database =/ s/= .*/= new_value/' /path/to/file
Run Code Online (Sandbox Code Playgroud)

说明:

  • -i告诉sed将结果保存到输入文件中.如果没有它,sed会将结果打印到stdout.
  • /central.database =/ 匹配包含斜杠之间字符串的行,即"central.database =".
  • s/OLD/NEW/部分执行一个小号 ubstitution.OLD字符串是要匹配的正则表达式,而NEW部分是要替换的字符串.
  • 在正则表达式中,.*表示"匹配任何内容".所以= .*匹配等号,空格,然后是其他任何东西.


sap*_*pht 56

这是一个示例表达式:

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

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

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

或者使用可变扩展:

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

在你的例子中:

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

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

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

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

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

-i用于替换输入文件中的数据.否则sed会写入stdout.

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


Ale*_*thy 8

我知道为这个问题添加一个答案为时已晚,我想与大家分享我的知识.我已经采用了一种非常通用的方法来解决类似的问题.我删除了匹配字符串的整行,并将所需的值添加到该键.对于你的问题,这里是答案

replaceValue=SQLTEST
sed -i "/central.database =/d" /home/testing.txt
echo "central.database = $replaceValue"  >> /home/testing.txt
Run Code Online (Sandbox Code Playgroud)

sed从文件中删除匹配的字符串行,紧接的下一行是将所需的键和值插入到文件中.

  • 如果您不知道密钥已存在,这是最佳答案.我认为简单性更好,你将有更少的逃避问题 (2认同)

fed*_*qui 5

我喜欢使用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
Run Code Online (Sandbox Code Playgroud)

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

例如:

$ cat conf
hello
my_var= SOME VALUE
#my_var = ANOTHER VALUE
bye
Run Code Online (Sandbox Code Playgroud)

让我们将值更改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
Run Code Online (Sandbox Code Playgroud)

也可以在 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
Run Code Online (Sandbox Code Playgroud)

您当然可以将所有这些放在一个 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" 
Run Code Online (Sandbox Code Playgroud)

执行后,这将返回

hello
my_var= NEW VALUE
#my_var = ANOTHER VALUE
bye
Run Code Online (Sandbox Code Playgroud)

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