防止在 echo 参数中扩展 \c

Prevent expansion of \c in echo argument

我正在用 echo 构建一个 shell 脚本。我有类似的东西:

echo "sed -i \"\|charlie\.url\s*=\s*.*|c\charlie.url = ${CHARLIE_URL}\" foo.conf" >> bar.sh

即替换 foo.conf 中包含当前 charlie.url 的行(不一定在开头,因为该行可能是评论)换行新 url.

我希望bar.sh的输出是

sed -i "\|charlie\.url\s*=\s*.*|c\charlie.url = ${CHARLIE_URL}" foo.conf

然而,c\charlie 被解释为 c \c harlie, 代替 c\ charlie,生成以下输出:

sed -i "\|charlie\.url\s*=\s*.*|c

我发现我可以通过使用单引号而不是双引号来防止这种情况发生,但在那种情况下 ${CHARLIE_URL}(我确实需要展开)不会展开。

我的 echo 参数应该是什么样的?

我正在使用 破折号(Ubuntu 下的#!/bin/sh),但我也可以使用 bashzsh.

代替echo,您可以尝试cat

cat << EOF >> bar.sh
sed -i "\|charlie\.url\s*=\s*.*|c\charlie.url = ${CHARLIE_URL}" foo.conf
EOF
#!/bin/bash

# bash will expand content within "" and stuff like $URL gets expanded
# also double-backslash reduces to a single; bash wouldn't expand stuff within ''

URL="https..."
echo double: "c\charlie.url, URL $URL"
echo single: 'c\charlie.url, URL $URL'

# if you need to output a \
echo "\\"

命令行使用第一个斜杠引用第二个斜杠。如果CHARLIE_URL=foo,你的echo实际上输出的是

sed -i "\|charlie\.url\s*=\s*.*|c\charlie.url = foo" foo.conf

尝试使用单引号,但 close/open 它们围绕变量。

echo 'sed -i "\|charlie\.url\s*=\s*.*|c\charlie.url = '"${CHARLIE_URL}"'" foo.conf'

这会产生

sed -i "\|charlie\.url\s*=\s*.*|c\charlie.url = foo" foo.conf

如前所述,您也可以引用引用斜杠的斜杠,然后引用另一个斜杠引用的斜杠,以便后续迭代将它们归结为您想要的...但这通常是一团糟,并导致倾斜牙签综合症。

有人已经在 here-doc 中提出了很好的建议,所以我不再重复,但您也可以使用我通常更喜欢的 "here string"。

cat <<< "sed -i '\|charlie\.url\s*=\s*.*|c\charlie.url = ${CHARLIE_URL}' foo.conf"

我将你脚本中的双引号换成了单引号,假设你想要的是将 $CHARLIE_URL 的字面值输出到你的脚本中。如果您希望脚本使用变量,无论在运行时分配什么值,那么也引用它 -

cat <<< "sed -i '\|charlie\.url\s*=\s*.*|c\charlie.url = ${CHARLIE_URL}' foo.conf"