如何使用 sed 更改我的配置文件,并使用灵活的键和值?
- 2024-10-11 08:36:00
- admin 原创
- 73
问题描述:
我想在配置文件中搜索此表达式:“central.database”。然后我想将与“central.database”相关的设置更改为“SQLTEST”。
配置文件的布局最初看起来像这样:
central.database = SQLFIRSTTEST
这是我希望 sed 替换后的样子:
central.database = SQLTEST
我正在 bash 脚本中执行此操作,欢迎提供任何建议、推荐或替代解决方案!
(实际上这里的central.database
和都SQLTEST
来自 bash 变量。)
我当前的代码(第三次尝试):
sshRetValue=$(ssh -p "35903" -i $HOME/sshids/idrsa-1.old ${1} <<EOF
sed -i "s/^($CENTRAL_DB_NAMEs*=s*).*$/$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
解决方案 1:
sed -i -e '/central.database =/ s/= .*/= new_value/' /path/to/file
解释:
-i
告诉 sed 将结果保存到输入文件。如果没有它,sed 将把结果打印到 stdout。/central.database =/
匹配包含斜杠之间的字符串的行:central.database =
。.
由于它是正则表达式中的特殊字符,因此被转义。部分
s/OLD/NEW/
执行替换。OLD 字符串是要匹配的正则表达式,部分NEW
是要替换的字符串。在正则表达式中,
.*
表示“匹配任何内容”。因此= .*
匹配等号、空格,然后是其后的任何其他内容。
解决方案 2:
这是一个示例表达式:
sed -i 's/^(central.databases*=s*).*$/SQLTEST/' file.cfg
如果您想要匹配/
其中的内容,您可以使用另一个分隔符:
sed -i 's#^(cent/ral.data/bases*=s*).*$#SQL/TEST#' file.cfg
或者使用变量扩展:
VAL="SQLTEST"
sed -i "s/^(central.databases*=s*).*$/$VAL/" file.cfg
在您的示例中:
sshRetValue=`sed -i "s/^($CENTRAL_DB_NAMEs*=s*).*$/$CENTRAL_DB_VALUE/" /home/testing.txt`;
$CENTRAL_DB_NAME 前面有一个 1,这是无效的。此外,sed 不会打印其返回值。这是检查返回值的首选方法:
sed -i "s/^($CENTRAL_DB_NAMEs*=s*).*$/$CENTRAL_DB_VALUE/" /home/testing.txt;
sed_return_value=$?
最后通过管道传输到 ssh(未经测试):
sed_return_value=$(ssh server <<EOF
sed -i "s/^($CENTRAL_DB_NAMEs*=s*).*$/$CENTRAL_DB_VALUE/" /home/testing.txt;
echo $?
EOF
)
-i 用于替换输入文件中的数据。否则 sed 将写入 stdout。
正则表达式本身就是一个领域。在 stackoverflow 答案中不可能深入解释它们,除非你无法理解某些特定功能。
解决方案 3:
我知道现在回答这个问题已经太晚了,但我想和大家分享我的知识。我曾经使用过一种非常通用的方法来解决类似的问题。我删除了与字符串匹配的整行,并将所需的值添加到该键。对于你的问题,以下是答案
replaceValue=SQLTEST
sed -i "/central.database =/d" /home/testing.txt
echo "central.database = $replaceValue" >> /home/testing.txt
sed 从文件中删除匹配的字符串行,紧接着的下一行将所需的键和值插入到文件。
解决方案 4:
我喜欢使用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
为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
还可以设置 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"
然后将它们传递给函数。
解决方案 5:
如果您想在两个属性文件之间进行替换,您可以使用以下命令:
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
解决方案 6:
我有一个名为“config.php”的文件,我想更改其中的一行定义。
例如,以下行:
define('SOME_CONSTANT', 'old_value');
必须用这个替换:
define('SOME_CONSTANT', 'new_value');
所以我这样做了:
sed -i -e "/.*SOME_CONSTANT*./ s/.*/define('SOME_CONSTANT', 'new_value');/" path/to/config.php
在第一部分中,我正在寻找包含“SOME_CONSTANT”的行(因此是通配符)
然后我用新的定义替换该行,例如:define('SOME_CONSTANT', 'new_value');
在 Centos 7 上测试并运行良好
解决方案 7:
示例
假设我们想要更新 Postgres 配置文件以增加连接数。
我们想要更新此行/var/lib/postgresql/data/postgresql.conf
:
max_connections = 100
使用 sed:
sed -i 's/max_connections = 100/max_connections = 250/g' /var/lib/postgresql/data/postgresql.conf
在更新 Docker 配置文件时这非常有用,因为任何更新都需要自动化。
解决方案 8:
我使用这个脚本来保持优先级。
参数 $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
}
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件