我想让tcl在MSys / MinGW(来自mingw.org)下转义一个字符串。 tcl的版本来自mingw.org(截至2013年12月,通过mingw-get)。
在bash中,我可以用字符串(简化示例):
printf %q 'a \b $2'
printf '%q' "a \ b \' \" \$2"
返回:
a\ \\b\ \$2
a\ \\b\ \\\'\ \"\ \$2
分别
但是,如果字符串存储在变量中或从文件中读取,我无法使第二个示例在tclsh或tcl中工作。我尝试过的事情是:
% set s {a \b ' " $2}
% printf %q $s
/usr/bin/printf: %q: invalid conversion specification
child process exited abnormally
(我猜这是因为msys printf.exe与tclsh不能很好地协同工作)。
%exec bash -c "printf %q $s"
/usr/bin/bash: -c: line 0: unexpected EOF while looking for matching `''
/usr/bin/bash: -c: line 1: syntax error: unexpected end of file
(在这里,我甚至不知道如何正确引用$ s,考虑$ s内的单引号和双引号)。知道如何使这项工作吗?
由于
- 更新 -
答案@Donal Fellows适用于原始字符串。我有:
% exec bash -c {printf %q "$0"} $s
a\ \\b\ \'\ \"\ \ \$2
但它对我第一次遇到的测试字符串不起作用。如果字符串中有一个结束行,答案似乎不起作用。
% set s1 {a \b ' "
$2 }
% exec bash -c {printf %q "$0"} $s1
我期待的是:
a\ \\b\ \'\ \"\ \n\ \$2
奇怪的是,上面的exec
会返回:
$'a \\b \' " \n $2 '
似乎搞砸了。有一个不需要的前导$'
,双引号"
未正确转义。并且空白不会像以前一样转义为
\
。有什么想法吗?
- 更新2 -
正如@Donal Fellows所解释的那样,上面的字符串$'a \\b \' " \n $2 '
是一个bash特殊的引用形式。我最后一个问题是如何在tcl中逃避/使用这种特殊形式。例如:
set s { ls
echo '"' }
set ss [exec bash -c {printf %q "$0"} $s]
返回:
$' ls\n echo \'"\' '
我可以在bash(msys / mingw)中使用这个特殊的表单字符串:
eval $' ls\n echo \'"\' '
执行两行命令(ls和echo'“'),并返回,例如:
a.txt
"
但是,我无法弄清楚如何在tclsh中完成这项工作。
% exec bash -c {eval $ss}
根本不返回任何内容。我尝试了其他一些组合。没有用。有关如何逃避/解除这一点的任何指示?
由于
答案 0 :(得分:2)
printf
既是msys 中的命令,也是 bash内置的命令。 只有bash内置支持%q
。这意味着从Tcl调用它比平常更棘手,因为你必须协商bash的引用。这需要这种相当尴尬的结构:
exec bash -c {printf %q "$0"} $s
大括号中的部分是shell语法,但其余部分是Tcl语法;通过这样做,它将与(以及正确的shell引用)任何输入一起使用。请注意,Tcl的大括号就像bourne shell单引号一样,除了它们是可嵌套的。
如果您想在bash中使用特殊表单,则将其替换为Tcl 中的bash脚本:
set quoted [exec bash -c {printf %q "$0"} $s]
exec bash -c "eval $quoted"
(这没关系。printf %q
完全引用了这项工作;这就是它的目的。)
如果你有一个复杂的脚本将使用你不想这样做的引用片段,你最终会再次将其作为参数传递,并在必要时使用另一个eval
:
exec bash -c {
# You can get *really* complicated in here!
eval eval "$0"
} $quoted
但如果这种情况继续下去,可能是时候考虑一下你的方法是否合适......