我试图捕捉一个文件来创建自己的副本,但同时替换一些值
我的命令是:
cat ${FILE} | sed "s|${key}|${value}|g" > ${TEMP_FILE}
然而,当我打开临时文件时,没有任何键被替换 - 只是直接交换。我已经回应了键和值的值,它们是正确的 - 它们来自数组元素。
然而,如果我使用普通字符串而不是变量,它适用于一种类型的键 - 即:
cat ${FILE} | sed "s|example_key|${value}|g" > ${TEMP_FILE}
文件中的example_key实例被替换,这就是我想要的。
但是,当我尝试使用我的数组$ key参数时,它什么也没做。不明白为什么: - (
命令用法:
declare -a props
...
....
for x in "${props[@]}"
do
key=`echo "${x}" | cut -d '=' -f 1`
value=`echo "${x}" | cut -d '=' -f 2`
# global replace on the $FILE
cat ${FILE} | sed "s|${key}|${value}|g" > ${TEMP_FILE}
#cat ${FILE} | sed "s|example_key|${value}|g" > ${TEMP_FILE}
done
数组元素以以下格式存储:$ key = $ value
答案 0 :(得分:4)
key='echo "${x}" | cut -d '=' -f 1
value='echo "${x}" | cut -d '=' -f 2
如果要进行命令替换,请使用反向标记,而不是单引号。
key=`echo "${x}" | cut -d '=' -f 1`
value=`echo "${x}" | cut -d '=' -f 2`
另请注意,当您遍历一系列key=value
对时,您每次都会覆盖临时文件,只使用一个替换应用于原始文件。所以在循环结束后,最好你可以希望只会应用最后一次替换。
我还建议不要在多次传递中执行此操作 - 通过将多个表达式传递给sed来执行此操作:
for x in "${props[@]}" ; do
subst="$subst -e 's=$x=g'"
done
sed $subst "${FILE}" > "${TEMP_FILE}"
我正在使用一个技巧,通过使用=
作为sed替换表达式的分隔符,我们不必将键与值分开。命令只是变成:
sed -e 's=foo=1=g' -e 's=bar=2=g' "${FILE}" > "${TEMP_FILE}"
答案 1 :(得分:2)
感谢@BillKarwin发现问题的关键:循环的每次迭代都会消除先前迭代的替换,因为单个键值对替换的结果取代了整个输出每次都提交。
尝试以下方法:
declare -a props
# ...
cp "$FILE" "$TEMP_FILE"
for x in "${props[@]}"; do
IFS='=' read -r key value <<<"$x"
sed -i '' "s|${key}|${value}|g" "${TEMP_FILE}"
done
sed
的{{1}}选项) -i
简化了代码,以便将每一行解析为键和值。更新:@BillKarwin提出了一个很好的观点:在循环中逐个执行替换是效率低下的。
这是一个完全避免循环的单行程序:
read
sed -f <(awk -F'=' '{ if ($0) print "s/" $1 "/" substr($0, 1+length($1)) "/g" }' \
"$FILE") "$FILE" > "$TEMP_FILE"
为awk
构建整套替换命令(每行一个)。sed
sed
。-f
个字符的情况。正确。