如何“反转义”bash的`printf“%q”`输出

4
在bash中,您可以使用printf "%q"来转义字符串中的特殊字符。为了清晰起见,在以下示例中添加了一个换行符:
$ printf "%q\n" "foo"
foo
$ printf "%q\n" 'foo$bar'
foo\$bar
$ printf "%q\n" "foo    bar"  # Tab entered with Ctrl+V Tab
$'foo\tbar'

你可以在printf命令后加上-v选项,将输出内容存储到一个变量中,而不是打印到标准输出流。
那么如果我想要将原始的未转义的字符串输出到标准输出流,该怎么办呢?如果只使用简单的echo命令,会包含所有的元字符和控制字符;使用echo -e命令会有所改善,但并不能完全实现字符串未转义的需求。

3
bash 可以取消转义:bash -c "echo ${var}" - hek2mgl
整洁:谢谢@hek2mgl。如果您将此作为答案添加,我会接受:) - Xophmeister
嗯,这只是一个想法。我对此并不满意。它重新引入了那些在使用“printf $q”时避免的风险。 - hek2mgl
没错,它容易受到代码注入攻击... 真遗憾 :P - Xophmeister
也许不是:printf -v X "%q" '$(touch foo)'; Y="$(bash -c "echo $X")"; echo "$Y"$Y 设置为并回显 $(touch foo),但 touch foo 没有被执行。 - Xophmeister
1个回答

2
使用printfeval来“取消转义”字符串(因为它已经被bash引用,所以是完全安全的)。echo通常对任意用户输入都是危险的。
eval printf '%s\\n' "$var"

printf的参数是%s\\n,即使在单引号内也要使用双反斜杠,因为eval会将其作为一个参数并剥离(评估)它,所以它实际上变成了这样:printf %s\\n $'12\n34 56',这是一个完全安全和有效的命令(变量甚至包括换行符和空格,如您所见)。

注意:这假定输入已从printf '%q'或类似方法中转义,否则不安全


这个解决方案似乎不安全。var='a b; ls'; eval printf '%s\\n' "$var" 显示了我的工作目录的内容。 - eivour
显然,它假设输入已从printf '%q'中转义,在这种情况下,它是安全的,因为;不能出现在输入中,只有;(它的转义形式)。我编辑添加了这些信息。 - kktsuri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接