4

我正在尝试使用 R 从 R 运行一些 Perl system:只需将字符串(在 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将 last 解释\'为嵌入的引号$str,而不是转义的反斜杠。事实上,要让 perl 回显我需要做的反斜杠

> echo('\\\\')
'/usr/bin/perl' -e "\$str='\\\\'; print \$str"
\ # <-- prints this

也就是说,我需要为Perl转义我的反斜杠转义我的反斜杠(除了我在 R/bash 中转义它们)。

我怎样才能确保在echo用户输入的字符串是打印的字符串?即唯一需要的转义级别是在 R 级别上?

即是否有某种类似的perlQuote功能shQuote?我应该手动转义echo函数中的所有反斜杠吗?有没有我需要逃脱的其他角色?

4

2 回答 2

6

不要生成代码。这很难。相反,将参数作为参数传递:

echo <- function (string) {
    cmd <- paste(shQuote(Sys.which('perl')),
                 '-e', shQuote('my ($str) = @ARGV; print $str;'),
                 shQuote(string))
    message(cmd)
    system(cmd)
}

(您也可以使用环境变量。)

(我以前从未使用过甚至见过 R 代码,所以请原谅任何语法错误。)

于 2013-05-19T09:39:22.280 回答
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("\\\\")
于 2013-05-19T08:46:36.053 回答