我正在编写一个bash脚本来修改包含一堆键/值对的配置文件。如何读取密钥并找到值并可能修改它?
答案 0 :(得分:86)
在黑暗中用于修改单个值的狂野刺:
sed -c -i "s/\($TARGET_KEY *= *\).*/\1$REPLACEMENT_VALUE/" $CONFIG_FILE
假设目标键和替换值不包含任何特殊的正则表达式字符,并且键值分隔符为“=”。注意,-c选项是系统相关的,您可能需要省略它才能执行sed。
有关如何进行类似替换的其他提示(例如,当REPLACEMENT_VALUE中包含'/'字符时),there are some great examples here。
答案 1 :(得分:12)
希望这有助于某人。我创建了一个自包含的脚本,它需要对各种进行配置处理。
#!/bin/bash
CONFIG="/tmp/test.cfg"
# Use this to set the new config value, needs 2 parameters.
# You could check that $1 and $1 is set, but I am lazy
function set_config(){
sudo sed -i "s/^\($1\s*=\s*\).*\$/\1$2/" $CONFIG
}
# INITIALIZE CONFIG IF IT'S MISSING
if [ ! -e "${CONFIG}" ] ; then
# Set default variable value
sudo touch $CONFIG
echo "myname=\"Test\"" | sudo tee --append $CONFIG
fi
# LOAD THE CONFIG FILE
source $CONFIG
echo "${myname}" # SHOULD OUTPUT DEFAULT (test) ON FIRST RUN
myname="Erl"
echo "${myname}" # SHOULD OUTPUT Erl
set_config myname $myname # SETS THE NEW VALUE
答案 2 :(得分:3)
假设您有一个key=value
对的文件,可能在=
周围有空格,您可以使用awk
随意删除,修改就地或追加键值对即使键或值包含特殊的正则表达式序列:
# Using awk to delete, modify or append keys
# In case of an error the original configuration file is left intact
# Also leaves a timestamped backup copy (omit the cp -p if none is required)
CONFIG_FILE=file.conf
cp -p "$CONFIG_FILE" "$CONFIG_FILE.orig.`date \"+%Y%m%d_%H%M%S\"`" &&
awk -F '[ \t]*=[ \t]*' '$1=="keytodelete" { next } $1=="keytomodify" { print "keytomodify=newvalue" ; next } { print } END { print "keytoappend=value" }' "$CONFIG_FILE" >"$CONFIG_FILE~" &&
mv "$CONFIG_FILE~" "$CONFIG_FILE" ||
echo "an error has occurred (permissions? disk space?)"
答案 3 :(得分:2)
sed "/^$old/s/\(.[^=]*\)\([ \t]*=[ \t]*\)\(.[^=]*\)/\1\2$replace/" configfile
答案 4 :(得分:1)
所以我不能为此付出任何功劳,因为它是stackoverflow答案和irc.freenode.net #bash通道的帮助的结合体,但现在有bash函数既可以设置也可以读取配置文件值:
# https://stackoverflow.com/a/2464883
# Usage: config_set filename key value
function config_set() {
local file=$1
local key=$2
local val=${@:3}
ensureConfigFileExists "${file}"
# create key if not exists
if ! grep -q "^${key}=" ${file}; then
# insert a newline just in case the file does not end with one
printf "\n${key}=" >> ${file}
fi
chc "$file" "$key" "$val"
}
function ensureConfigFileExists() {
if [ ! -e "$1" ] ; then
if [ -e "$1.example" ]; then
cp "$1.example" "$1";
else
touch "$1"
fi
fi
}
# thanks to ixz in #bash on irc.freenode.net
function chc() { gawk -v OFS== -v FS== -e 'BEGIN { ARGC = 1 } $1 == ARGV[2] { print ARGV[4] ? ARGV[4] : $1, ARGV[3]; next } 1' "$@" <"$1" >"$1.1"; mv "$1"{.1,}; }
# https://unix.stackexchange.com/a/331965/312709
# Usage: local myvar="$(config_get myvar)"
function config_get() {
val="$(config_read_file ${CONFIG_FILE} "${1}")";
if [ "${val}" = "__UNDEFINED__" ]; then
val="$(config_read_file ${CONFIG_FILE}.example "${1}")";
fi
printf -- "%s" "${val}";
}
function config_read_file() {
(grep -E "^${2}=" -m 1 "${1}" 2>/dev/null || echo "VAR=__UNDEFINED__") | head -n 1 | cut -d '=' -f 2-;
}
起初,我使用的是接受答案的sed解决方案:https://stackoverflow.com/a/2464883/2683059
但是,如果该值包含/字符,则会中断
答案 5 :(得分:0)
一般情况下,使用grep和cut提取信息很容易:
cat "$FILE" | grep "^${KEY}${DELIMITER}" | cut -f2- -d"$DELIMITER"
更新你可以做这样的事情:
mv "$FILE" "$FILE.bak"
cat "$FILE.bak" | grep -v "^${KEY}${DELIMITER}" > "$FILE"
echo "${KEY}${DELIMITER}${NEWVALUE}" >> "$FILE"
这显然不会维持键值对的顺序。添加错误检查以确保您不会丢失数据。
答案 6 :(得分:-1)
假设您的配置文件格式如下:
CONFIG_NUM=4
CONFIG_NUM2=5
CONFIG_DEBUG=n
在bash脚本中,您可以使用:
CONFIG_FILE=your_config_file
. $CONFIG_FILE
if [ $CONFIG_DEBUG == "y" ]; then
......
else
......
fi
$CONFIG_NUM
,$CONFIG_NUM2
,$CONFIG_DEBUG
就是您所需要的。
阅读完值后,将其写回将很容易:
echo "CONFIG_DEBUG=y" >> $CONFIG_FILE