在 dockerfile 中使用 sed 或 awk 编辑 conf 文件并更改值?
Edit conf files and change values with sed or awk in the dockerfile?
我有一堆conf文件,可以描述为两种类型:
类型 1(典型的类似 conf 文件的 ini 文件):
[server]
# Protocol (http, https)
;protocol = http
# The ip address to bind to, empty will bind to all interfaces
;http_addr = 192.168.33.2
# The http port to use
;http_port = 3000
类型 2(格式错误的 conf 文件):
###
### [http]
###
[http]
# Determines whether HTTP endpoint is enabled.
# enabled = true
# The bind address used by the HTTP service.
# bind-address = ":8080"
对于 Type1 conf 文件,我可以成功地使用像 crudini p.a 和 crudini --set filename.conf server protocol https
这样的工具,它实际上在服务器部分下添加了一个新条目,而不是取消对现有条目的注释。只要它能正常工作。
crudini 对类型 2 文件失败并出现解析错误,因为 conf 文件不是正确的 ini 文件。对于这些,我尝试使用 sed 但失败了。
我想要实现的是使用一个 script/tool 来修改两种类型的文件。也许一个好的方法是:
- 首先找到该部分,但忽略以
;
或 #
和部分名称 开头的行
- 在该部分的所有行中搜索参数。
- 如果参数行以
;
或#
开头,则替换整行(这也去掉了空格并将其插入相同位置)
- 如果没有找到参数,应该添加
我找到了很多脚本,其中有很多代码,但需要一个使用 Docker 配置文件的小型解决方案。
你能帮我找到一个优雅的解决方案吗?
这里。向前支付。腿部工作由 gawk 处理。我用 --posix
开关对其进行了测试,因此我认为它也应该适用于 mawk 和其他 awk 变体。
脚本将引用包含空格和等号的值,以及引用被替换值的值。我不熟悉 Docker 文件,但由于在您的第二个示例中引用了“:8000”,我认为引用可能很重要。
#!/bin/bash
usage() {
echo "Usage: $(basename [=10=]) -s section -i item -v value filename"
exit
}
export LC_ALL=C
while getopts "s:i:v:" i || (( $# )); do {
case $i in
s) section="$OPTARG";;
i) item="$OPTARG";;
v) value="$OPTARG";;
?) [[ -f ]] && filename="";shift;;
esac
}; done
[[ -z "$section" ]] || [[ -z "$item" ]] || [[ -z "$filename" ]] && usage
[[ -w "$filename" ]] && {
tmpfile="$(mktemp -p /dev/shm)"
[[ $(whoami) = "root" ]] && chown --reference="$filename" "$tmpfile"
chmod --reference="$filename" "$tmpfile"
} || {
echo "Invalid filename: $filename"
usage
}
cleanup() {
[[ -f "$tmpfile" ]] && rm -f "$tmpfile"
exit
}
trap cleanup EXIT
awk -v section="$section" -v item="$item" -v value="$value" '
function quote(str) { return "\"" str "\"" }
/^\[[^\]]+\]/ {
if (flag) {
printf "%s = %s\n", item, value ~ /[[:space:]=]/ ? quote(value) : value
flag = 0
}
else flag = (section == substr([=10=], 2, index([=10=], "]") - 2))
}
[=10=] ~ ("^[[:space:]#;]*" item "[[:space:]]*=") {
if (flag) {
[=10=] = sprintf("%s = %s", item, /"/ || value ~ /[[:space:]=]/ ? quote(value) : value)
flag = 0
}
}
1
END { if (flag) printf "%s = %s", item, value ~ /[[:space:]=]/ ? quote(value) : value }
' "$filename" >"$tmpfile"
[[ -s "$tmpfile" ]] && mv "$tmpfile" "$filename" || echo "Something went horribly wrong."
我有一堆conf文件,可以描述为两种类型:
类型 1(典型的类似 conf 文件的 ini 文件):
[server]
# Protocol (http, https)
;protocol = http
# The ip address to bind to, empty will bind to all interfaces
;http_addr = 192.168.33.2
# The http port to use
;http_port = 3000
类型 2(格式错误的 conf 文件):
###
### [http]
###
[http]
# Determines whether HTTP endpoint is enabled.
# enabled = true
# The bind address used by the HTTP service.
# bind-address = ":8080"
对于 Type1 conf 文件,我可以成功地使用像 crudini p.a 和 crudini --set filename.conf server protocol https
这样的工具,它实际上在服务器部分下添加了一个新条目,而不是取消对现有条目的注释。只要它能正常工作。
crudini 对类型 2 文件失败并出现解析错误,因为 conf 文件不是正确的 ini 文件。对于这些,我尝试使用 sed 但失败了。
我想要实现的是使用一个 script/tool 来修改两种类型的文件。也许一个好的方法是:
- 首先找到该部分,但忽略以
;
或#
和部分名称 开头的行
- 在该部分的所有行中搜索参数。
- 如果参数行以
;
或#
开头,则替换整行(这也去掉了空格并将其插入相同位置) - 如果没有找到参数,应该添加
- 如果参数行以
我找到了很多脚本,其中有很多代码,但需要一个使用 Docker 配置文件的小型解决方案。
你能帮我找到一个优雅的解决方案吗?
这里。向前支付。腿部工作由 gawk 处理。我用 --posix
开关对其进行了测试,因此我认为它也应该适用于 mawk 和其他 awk 变体。
脚本将引用包含空格和等号的值,以及引用被替换值的值。我不熟悉 Docker 文件,但由于在您的第二个示例中引用了“:8000”,我认为引用可能很重要。
#!/bin/bash
usage() {
echo "Usage: $(basename [=10=]) -s section -i item -v value filename"
exit
}
export LC_ALL=C
while getopts "s:i:v:" i || (( $# )); do {
case $i in
s) section="$OPTARG";;
i) item="$OPTARG";;
v) value="$OPTARG";;
?) [[ -f ]] && filename="";shift;;
esac
}; done
[[ -z "$section" ]] || [[ -z "$item" ]] || [[ -z "$filename" ]] && usage
[[ -w "$filename" ]] && {
tmpfile="$(mktemp -p /dev/shm)"
[[ $(whoami) = "root" ]] && chown --reference="$filename" "$tmpfile"
chmod --reference="$filename" "$tmpfile"
} || {
echo "Invalid filename: $filename"
usage
}
cleanup() {
[[ -f "$tmpfile" ]] && rm -f "$tmpfile"
exit
}
trap cleanup EXIT
awk -v section="$section" -v item="$item" -v value="$value" '
function quote(str) { return "\"" str "\"" }
/^\[[^\]]+\]/ {
if (flag) {
printf "%s = %s\n", item, value ~ /[[:space:]=]/ ? quote(value) : value
flag = 0
}
else flag = (section == substr([=10=], 2, index([=10=], "]") - 2))
}
[=10=] ~ ("^[[:space:]#;]*" item "[[:space:]]*=") {
if (flag) {
[=10=] = sprintf("%s = %s", item, /"/ || value ~ /[[:space:]=]/ ? quote(value) : value)
flag = 0
}
}
1
END { if (flag) printf "%s = %s", item, value ~ /[[:space:]=]/ ? quote(value) : value }
' "$filename" >"$tmpfile"
[[ -s "$tmpfile" ]] && mv "$tmpfile" "$filename" || echo "Something went horribly wrong."