2013-05-19 27 views
4

我试图从R运行一些Perl使用system:简单地分配一个字符串(R中提供)给变量并回显它。 (该system呼叫/bin/sh执行)从R执行Perl - perlQuote/shQuote?

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

(我正在尝试为R与'fortunes'软件包结合使用'cowsay'软件包,所以问题是一个好的原因!)) –

回答

6

不生成代码。这很难。相反,传递参数作为参数:(你也可以使用一个环境变量)

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

(我从来没有用过或之前见过R代码里面,所以请原谅所有语法错误。)

+0

太棒了!我不知道@ARGV。干杯! –

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("\\\\")