如何使用 bash 脚本通过使用 属性 文件作为输入将文件中的键替换为值
How to use bash script to replace keys with values in files by using a property file as the input
我有几个配置文件,其中包含可配置的数据。例子(看${ConnectorPort}
):
<Connector port="${ConnectorPort}" protocol="HTTP/1.1" server="MyServer"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"/>
在配置时,我想用给定属性文件中的值替换键。
问题是需要很长的时间(每个文件几秒钟)来遍历所有文件并遍历所有属性以检查每个 属性。下面的脚本。
知道如何使用 bash 更快地完成吗?
也许 sed 或 awk 中有一种方法可以将所有属性作为单个输入获取?
也许在内存中进行替换?
脚本:
for file in "${files[@]}"
do
# echo ------
#echo In file: $file
#echo ------
cp -f "$file" "$file.bak"
unset replaced
for prop in "${!props[@]}"
do
key="$prop"
keyToReplace="${$prop}"
val="${props[$key]}"
# echo In prop: $key=$val
sed -i "s|$keyToReplace|$val|Igw $file.change" "$file"
assertReturnStatus $? "sed failed"
if [ -z "$replaced" ] && [ -s "$file.change" ]; then
replaced=true
echo Replacing props in file "$file"
cp -n "$file.bak" "$file.orig"
fi
done
rm -f "$file.change"
rm -f "$file.bak"
done
* 其中一项要求是在文件更改时创建备份 (.orig)。
谢谢。
循环内的循环导致每个文件多次 sed
到 运行。所以,去掉循环里面的循环。
declare -a sedArgs
for prop in "${!props[@]}"
do
key="$prop"
keyToReplace="${$prop}"
val="${props[$key]}"
# echo In prop: $key=$val
#sed -i "s|$keyToReplace|$val|Igw $file.change" "$file"
sedArgs+=("-e")
sedArgs+=("s|$keyToReplace|$val|Ig")
done
for file in "${files[@]}"
do
# echo ------
#echo In file: "$file"
#echo ------
sed -i.orig "${sedArgs[@]}" $file
cmp -s "$file" "${file}.orig" && mv "${file}.orig" "$file"
done
内存解决方案,将内容读取到内存并在内存中进行替换:
for file in "${files[@]}"
do
# echo ------
# echo In file: $file
# echo ------
unset replaced
contentOrig=`cat "$file"`
content="$contentOrig"
for prop in "${!props[@]}"
do
# No need to search for all properties if there are
if [[ ! "$content" == *'${'* ]]; then
break
fi
key="$prop"
keyToReplace="${$prop}"
val="${props[$key]}"
# echo In prop: $key=$val
content="${content//$keyToReplace/$val}"
assertReturnStatus $? "sed failed"
done
# TODO: Show warning if `${` still exists (Excluding `*.sh` files). We might have forgotten to add a property.
if [[ "$content" != "$contentOrig" ]]; then
let "filesReplacedCount++"
cp -n "$file" "$file.orig"
echo "$content" > "$file"
echo Replaced props in file "$file"
fi
done
我有几个配置文件,其中包含可配置的数据。例子(看${ConnectorPort}
):
<Connector port="${ConnectorPort}" protocol="HTTP/1.1" server="MyServer"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"/>
在配置时,我想用给定属性文件中的值替换键。
问题是需要很长的时间(每个文件几秒钟)来遍历所有文件并遍历所有属性以检查每个 属性。下面的脚本。
知道如何使用 bash 更快地完成吗?
也许 sed 或 awk 中有一种方法可以将所有属性作为单个输入获取?
也许在内存中进行替换?
脚本:
for file in "${files[@]}"
do
# echo ------
#echo In file: $file
#echo ------
cp -f "$file" "$file.bak"
unset replaced
for prop in "${!props[@]}"
do
key="$prop"
keyToReplace="${$prop}"
val="${props[$key]}"
# echo In prop: $key=$val
sed -i "s|$keyToReplace|$val|Igw $file.change" "$file"
assertReturnStatus $? "sed failed"
if [ -z "$replaced" ] && [ -s "$file.change" ]; then
replaced=true
echo Replacing props in file "$file"
cp -n "$file.bak" "$file.orig"
fi
done
rm -f "$file.change"
rm -f "$file.bak"
done
* 其中一项要求是在文件更改时创建备份 (.orig)。
谢谢。
循环内的循环导致每个文件多次 sed
到 运行。所以,去掉循环里面的循环。
declare -a sedArgs
for prop in "${!props[@]}"
do
key="$prop"
keyToReplace="${$prop}"
val="${props[$key]}"
# echo In prop: $key=$val
#sed -i "s|$keyToReplace|$val|Igw $file.change" "$file"
sedArgs+=("-e")
sedArgs+=("s|$keyToReplace|$val|Ig")
done
for file in "${files[@]}"
do
# echo ------
#echo In file: "$file"
#echo ------
sed -i.orig "${sedArgs[@]}" $file
cmp -s "$file" "${file}.orig" && mv "${file}.orig" "$file"
done
内存解决方案,将内容读取到内存并在内存中进行替换:
for file in "${files[@]}"
do
# echo ------
# echo In file: $file
# echo ------
unset replaced
contentOrig=`cat "$file"`
content="$contentOrig"
for prop in "${!props[@]}"
do
# No need to search for all properties if there are
if [[ ! "$content" == *'${'* ]]; then
break
fi
key="$prop"
keyToReplace="${$prop}"
val="${props[$key]}"
# echo In prop: $key=$val
content="${content//$keyToReplace/$val}"
assertReturnStatus $? "sed failed"
done
# TODO: Show warning if `${` still exists (Excluding `*.sh` files). We might have forgotten to add a property.
if [[ "$content" != "$contentOrig" ]]; then
let "filesReplacedCount++"
cp -n "$file" "$file.orig"
echo "$content" > "$file"
echo Replaced props in file "$file"
fi
done