我正在尝试使用system
从R运行一些Perl:只需将一个字符串(在R中提供)分配给变量并回显它。 (system
调用在/bin/sh
)
echo <- function (string) {
cmd <- paste(shQuote(Sys.which('perl')),
'-e',
shQuote(sprintf("$str=%s; print $str", shQuote(string))))
message(cmd)
system(cmd)
}
# all fine:
# echo('hello world!')
# echo("'")
# echo('"')
# echo('foo\nbar')
但是,如果我尝试echo
反斜杠(或者实际上以反斜杠结尾的任何字符串),我会收到错误:
> echo('\\')
'/usr/bin/perl' -e "\$str='\\'; print \$str"
Can't find string terminator "'" anywhere before EOF at -e line 1.
(注意:$
前面的反斜杠很好,因为这可以保护/bin/sh
不会认为$str
是一个shell变量。
错误是因为 Perl 将最后\'
解释为$str
中的嵌入引号,而不是转义反斜杠。事实上,要让perl回应我需要做的反斜杠
> echo('\\\\')
'/usr/bin/perl' -e "\$str='\\\\'; print \$str"
\ # <-- prints this
也就是说,我需要为 Perl 转义我的反斜杠(除了我在R / bash中转义它们)。
如何在echo
中确保用户输入的字符串是打印的字符串?即所需的唯一转义级别是在R级别上?
即。是否存在某种与perlQuote
类似的shQuote
函数?我应该手动转义echo
函数中的所有反斜杠吗?我还需要逃避任何其他角色吗?
答案 0 :(得分:6)
不要生成代码。那很难。相反,将参数作为参数传递:
echo <- function (string) {
cmd <- paste(shQuote(Sys.which('perl')),
'-e', shQuote('my ($str) = @ARGV; print $str;'),
shQuote(string))
message(cmd)
system(cmd)
}
(您也可以使用环境变量。)
(我以前从未使用过或甚至没见过R代码,所以请原谅任何语法错误。)
答案 1 :(得分:3)
以下似乎有效。
在Perl中,我使用q//
而不是引号来避免shell引号出现问题。
perlQuote <- function(string) {
escaped_string <- gsub("\\\\", "\\\\\\\\", string)
escaped_string <- gsub("/", "\\/", escaped_string)
paste("q/", escaped_string, "/", sep="")
}
echo <- function (string) {
cmd <- paste(shQuote(Sys.which('perl')),
'-le',
shQuote(sprintf("$str=%s; print $str", perlQuote(string))))
message(cmd)
system(cmd)
}
echo(1)
echo("'"); echo("''"); echo("'\""); echo("'\"'")
echo('"'); echo('""'); echo('"\''); echo('"\'"');
echo("\\"); echo("\\\\")